解析Python面向对象:从小白到面向对象大师的蜕变之路

文章目录

  • 一 类和对象的概念
  • 二 类的认识
    • 2.1 类的定义和使用语法
    • 2.2 成员变量和成员方法
  • 三 类和对象
    • 3.1 类和对象的关系
    • 3.2 构造方法
    • 3.3 魔术方法概述(内置类方法)
    • 3.4 内置方法详解
  • 四 面向对象三大特性
    • 4.1 封装
      • 4.1.1 封装的理解
      • 4.1.2 私有成员变量和方法
      • 4.1.3 封装练习案例
    • 4.2 继承
      • 4.2.1 基础语法
      • 4.2.2 pass关键字
      • 4.2.3 多继承注意事项
      • 4.2.4 复写
      • 4.2.5 调用父类同名成员
    • 4.3 类型注解
      • 4.3.1 变量的类型注解
      • 4.3.2 函数(方法)的类型注解
      • 4.2.3 Optional和Union类型
      • 4.2.4 自定义类型
      • 4.2.5 补充:PEP 484中定义的语法规则
    • 五 多态
      • 5.1 多态概念
    • 5.2 抽象类(接口)
  • 六 进阶内容
    • 使用对象组织数据
      • 1. 创建自定义类
      • 2. 数据结构的封装
      • 3. 组合和关联
      • 4. 继承和多态

一 类和对象的概念

  • Python 是一种面向对象的编程语言,它将数据和方法封装到对象中,使得代码更加模块化和易于维护。这意味着几乎所有的数据都是对象,并且所有的操作都是通过调用对象的方法来完成的。

类和对象的基本概念:

  • 类(Class):类是对象的模板或蓝图,它定义了对象应该有的属性和方法。在类中,可以定义初始化方法 __init__ 和其他方法,以及属性。

  • 对象(Object):对象是类的实例,它是根据类的定义创建的。每个对象都有自己的属性和方法,但是这些属性和方法都是根据类的定义来的。

    # 1. 设计类
    class Student:name=None;
    # 2. 创建对象
    stu_1=Student()
    stu_2=Student()
    # 3. 对象属性赋值
    stu_1.name="熊二"
    stu_2.name=	"翠花"
    

二 类的认识

2.1 类的定义和使用语法

  • 类(class)是一种用于创建对象(instances)的蓝图或模板。对象是类的实例,通过类可以定义对象的属性和方法。
  • 使用class是关键字定义类
    • 类的属性,即定义在类中的变量(成员变量)
    • 类的行为,即定义在类中的函数(成员方法)
      在这里插入图片描述
  • 类的定义语法
    # 定义一个类
    class 类名:类的属性类的方法
    
  • 创建类对象的语法
    对象名称=类名称()
    

2.2 成员变量和成员方法

  • 类中定义的属性(变量)——成员变量
  • 类中定义的行为(函数)——成员方法
    # 定义一个带有成员方法的类
    class Student:name = None     # 成员变量 学生姓名# 成员方法def say_hi(self):print(f"大家好呀,我是{self.name},欢迎大家多多关照")# 成员方法def say_hi2(self, msg):print(f"大家好,我是:{self.name}{msg}")stu = Student()
    stu.name = "周杰轮"
    stu.say_hi2("哎哟不错哟")
    
  • 在类中定义成员方法和定义函数基本一致,但仍有细微区别:
    def 方法名(self,形参1,...,形参n):方法体
    
  • 在方法定义的参数列表中,有一个:self关键字。self关键字是成员方法定义的时候,必须填写的,用来表示类对象自身的意思
  • 当使用类对象调用方法的是,self会自动被python传入在方法内部,想要访问类的成员变量,必须使用self

  • self关键字,尽管在参数列表中,但是传参的时候可以忽略它。
    stu = Student()
    stu.name = "周杰轮"
    stu.say_hi2("哎哟不错哟")
    

三 类和对象

3.1 类和对象的关系

  • 显示世界的事务和类
    在这里插入图片描述

  • 现实世界的事物也有属性和行为,类也有属性和行为。使用程序中的类,可以完美的描述现实世界的事物

  • 创建类对象的语法

    对象名称=类名称()
    
  • 类只是一种程序内的“设计图纸”,需要基于图纸生产实体(对象),才能正常工作这种套路,称之为:面向对象编程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.2 构造方法

  • Python类可以使用:__init__()方法,称之为构造方法。
    • 在创建类对象(构造类)的时候,会自动执行。
    • 在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用。
  • 在构造方法内定义成员变量,需要使用self关键字。原因:变量是定义在构造方法内部,如果要成为成员变量,需要用self来表示。
  • 演示
# 演示使用构造方法对成员变量进行赋值
# 构造方法的名称:__init__
class Student:# 该部分可以省略# ---------name=None;age=None;tel=None;# ---------def __init__(self, name, age ,tel):self.name = nameself.age = ageself.tel = telprint("Student类创建了一个类对象")stu = Student("周杰轮", 31, "18500006666")

3.3 魔术方法概述(内置类方法)

  • 在Python的类中,有一些特殊的内置方法(也称为魔术方法或双下划线方法),它们允许自定义类的行为,使其能够与Python的内置功能(如运算符、迭代等)进行交互。
  • 常见的Python类内置方法的列表:
方法名描述
__init__(self, ...)初始化方法,创建对象时自动调用。
__str__(self)返回对象的可打印字符串表示。
__repr__(self)返回对象的官方字符串表示,通常用于重新创建对象。
__len__(self)返回对象的长度。
__getitem__(self, key)当使用索引访问对象的元素时调用。
__setitem__(self, key, value)当使用索引赋值给对象的元素时调用。
__delitem__(self, key)当使用del obj[key]删除对象的元素时调用。
__iter__(self)返回一个可迭代对象,使对象可以被用于for循环。
__next__(self)在迭代对象时,每次调用next()函数时调用。
__eq__(self, other)当使用==运算符比较两个对象时调用。
__lt__(self, other)当使用<运算符比较两个对象时调用。
__gt__(self, other)当使用>运算符比较两个对象时调用。
__add__(self, other)当使用+运算符进行对象相加时调用。
__sub__(self, other)当使用-运算符进行对象相减时调用。
__mul__(self, other)当使用*运算符进行对象相乘时调用。
__divmod__(self, other)当使用divmod()函数进行对象除法和取余运算时调用。
__enter__(self)用于定义对象在with语句中的上下文管理行为。
__exit__(self, exc_type, exc_value, traceback)用于定义对象在with语句中的上下文管理行为。
  • 这些内置方法可以通过在类中实现相应的函数来自定义类的行为,使其与Python的内置功能进行交互。

3.4 内置方法详解

  • 在Python中定义一个类时,可以通过实现特定的内置方法来自定义类的行为。
  1. __init__(self, ...): 初始化方法,在创建对象时自动调用。用于初始化对象的属性。

示例:

class Person:def __init__(self, name, age):self.name = nameself.age = ageperson = Person("Alice", 25)
print(person.name)  # 输出: Alice
print(person.age)   # 输出: 25
  1. __str__(self): 返回对象的可打印字符串表示。

示例:

class Book:def __init__(self, title, author):self.title = titleself.author = authordef __str__(self):return f"Book: {self.title} by {self.author}"book = Book("The Great Gatsby", "F. Scott Fitzgerald")
print(book)  # 输出: Book: The Great Gatsby by F. Scott Fitzgerald
  1. __repr__(self): 返回对象的官方字符串表示,通常用于重新创建对象。

示例:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __repr__(self):return f"Point({self.x}, {self.y})"point = Point(3, 5)
print(repr(point))  # 输出: Point(3, 5)
  1. __len__(self): 返回对象的长度。

示例:

class MyList:def __init__(self, items):self.items = itemsdef __len__(self):return len(self.items)my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list))  # 输出: 5
  1. __getitem__(self, key): 当使用索引访问对象的元素时调用。

示例:

class MyList:def __init__(self, items):self.items = itemsdef __getitem__(self, index):return self.items[index]my_list = MyList([10, 20, 30])
print(my_list[1])  # 输出: 20
  1. __setitem__(self, key, value): 当使用索引赋值给对象的元素时调用。

示例:

class MyList:def __init__(self, items):self.items = itemsdef __setitem__(self, index, value):self.items[index] = valuemy_list = MyList([1, 2, 3])
my_list[1] = 10
print(my_list.items)  # 输出: [1, 10, 3]
  1. __delitem__(self, key): 当使用del obj[key]删除对象的元素时调用。

示例:

class MyList:def __init__(self, items):self.items = itemsdef __delitem__(self, index):del self.items[index]my_list = MyList([1, 2, 3])
del my_list[1]
print(my_list.items)  # 输出: [1, 3]
  1. __iter__(self): 返回一个可迭代对象,使对象可以被用于for循环。

示例:

class MyRange:def __init__(self, start, end):self.start = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.start >= self.end:raise StopIterationvalue = self.startself.start += 1return valuemy_range = MyRange(1, 4)
for num in my_range:print(num)  # 输出: 1 2 3
  1. __eq__(self, other): 当使用==运算符比较两个对象时调用。

示例:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __eq__(self, other):return self.x == other.x and self.y == other.ypoint1 = Point(3, 5)
point2 = Point(3, 5)
print(point1 == point2)  # 输出: True
  1. __lt__(self, other): 当使用<运算符比较两个对象时调用。

示例:

class Circle:def __init__(self, radius):self.radius = radiusdef __lt__(self, other):return self.radius < other.radiuscircle1 = Circle(5)
circle2 = Circle(8)
print(circle1 < circle2)  # 输出: True
  1. __gt__(self, other): 当使用>运算符比较两个对象时调用。

示例:

class Rectangle:def __init__(self, width, height):self.width = widthself.height = heightdef __gt__(self, other):return self.width * self.height > other.width * other.heightrectangle1 = Rectangle(4, 6)
rectangle2 = Rectangle(3, 8)
print(rectangle1 > rectangle2)  # 输出: False
  1. __add__(self, other): 当使用+运算符进行对象相加时调用。

示例:

class Vector:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):new_x = self.x + other.xnew_y = self.y + other.yreturn Vector(new_x, new_y)vector1 = Vector(2, 3)
vector2 = Vector(4, 1)
result = vector1 + vector2
print(result.x, result.y)  # 输出: 6 4
  1. __sub__(self, other): 当使用-运算符进行对象相减时调用。

示例:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __sub__(self, other):new_x = self.x - other.xnew_y = self.y - other.yreturn Point(new_x, new_y)point1 = Point(5, 8)
point2 = Point(3, 4)
result = point1 - point2
print(result.x, result.y)  # 输出: 2 4
  1. __mul__(self, other): 当使用*运算符进行对象相乘时调用。

示例:

class ComplexNumber:def __init__(self, real, imag):self.real = realself.imag = imagdef __mul__(self, other):new_real = self.real * other.real - self.imag * other.imagnew_imag = self.real * other.imag + self.imag * other.realreturn ComplexNumber(new_real, new_imag)complex1 = ComplexNumber(3, 2)
complex2 = ComplexNumber(1, 4)
result = complex1 * complex2
print(result.real, result.imag)  # 输出: -5 14
  1. __divmod__(self, other): 当使用divmod()函数进行对象除法和取余运算时调用。

示例:

class CustomNumber:def __init__(self, value):self.value = valuedef __divmod__(self, other):quotient = self.value // other.valueremainder = self.value % other.valuereturn quotient, remaindernum1 = CustomNumber(20)
num2 = CustomNumber(3)
quotient, remainder = divmod(num1, num2)
print(quotient, remainder)  # 输出: 6 2
  1. __enter__(self)__exit__(self, exc_type, exc_value, traceback): 用于定义对象在with语句中的上下文管理行为。

示例:

class FileManager:def __init__(self, filename, mode):self.filename = filenameself.mode = modedef __enter__(self):self.file = open(self.filename, self.mode)return self.filedef __exit__(self, exc_type, exc_value, traceback):self.file.close()with FileManager("example.txt", "r") as file:content = file.read()print(content)
# 文件在退出上下文后自动关闭

四 面向对象三大特性

  • 面向对象编程,是许多编程语言都支持的一种编程思想。
  • 简单理解:基于模板(类)去创建实体(对象),使用对象完成功能开发。

面向对象包含3大主要特性:

  • 封装
  • 继承
  • 多态

4.1 封装

4.1.1 封装的理解

在这里插入图片描述

  • 封装:将现实世界事物的属性和方法,封装到类中描述为成员变量、成员方法,从而完成程序对现实世界事物的描述。
  • 封装会对用户隐藏属性和方法
    在这里插入图片描述
  • 类中提供了私有成员的形式来支持隐藏属性和方法:私有成员变量、私有成员方法

4.1.2 私有成员变量和方法

定义私有成员的方式非常简单,只需要:

  • 私有成员变量:变量名以__开头(2个下划线)
  • 私有成员方法:方法名以__开头(2个下划线)
# 定义一个类,内含私有成员变量和私有成员方法
class Phone:# 私有成员变量__current_voltage = 0.5        # 当前手机运行电压# 私有成员方法def __keep_single_core(self):print("让CPU以单核模式运行")def call_by_5g(self):if self.__current_voltage >= 1:print("5g通话已开启")else:self.__keep_single_core()print("电量不足,无法使用5g通话,并已设置为单核运行进行省电。")phone = Phone()
phone.call_by_5g()
  • 私有方法无法直接被类对象使用
  • 私有变量无法赋值,也无法获取值
  • 私有成员无法被类对象使用,但是可以被其它的成员使用。
    在这里插入图片描述

4.1.3 封装练习案例

设计一个手机类,内部包含:

  • 私有成员变量:__is_5g_enable,类型bool,True表示开启5g,False表示关闭5g
  • 私有成员方法:__check_5g(),会判断私有成员__is_5g_enable的值
    • 若为True,打印输出:5g开启
    • 若为False,打印输出:5g关闭,使用4g网络
  • 公开成员方法:call_by_5g(),调用它会执行
    • 调用私有成员方法:__check_5g(),判断5g网络状态
    • 打印输出:正在通话中
      运行结果:
      在这里插入图片描述
# 设计一个类,用来描述手机
class Phone:# 提供私有成员变量:__is_5g_enable__is_5g_enable = False # 5g状态# 提供私有成员方法:__check_5g()def __check_5g(self):if self.__is_5g_enable:print("5g开启")else:print("5g关闭,使用4g网络")# 提供公开成员方法:call_by_5g()def call_by_5g(self):self.__check_5g()print("正在通话中")phone = Phone()
phone.call_by_5g()

4.2 继承

在这里插入图片描述

4.2.1 基础语法

  • 继承分为:单继承和多继承
  • 继承表示:将从父类那里继承(复制)来成员变量和成员方法(不含私有)
# 单继承
class 类名(父类名)类内容体
# 多继承
class 类名(父类1,父类2,...,父类N)类内容体	
# 演示单继承
class Phone:IMEI = None     # 序列号producer = "ITCAST" # 厂商def call_by_4g(self):print("4g通话")class Phone2022(Phone):face_id = "10001"       # 面部识别IDdef call_by_5g(self):print("2022年新功能:5g通话")phone = Phone2022()
print(phone.producer)
phone.call_by_4g()
phone.call_by_5g()
  • Python的类之间也支持多继承,即一个类,可以继承多个父类
    在这里插入图片描述
# 演示多继承
class NFCReader:nfc_type = "第五代"producer = "HM"def read_card(self):print("NFC读卡")def write_card(self):print("NFC写卡")class RemoteControl:rc_type = "红外遥控"def control(self):print("红外遥控开启了")class MyPhone(Phone, NFCReader, RemoteControl):passphone = MyPhone()
phone.call_by_4g()
phone.read_card()
phone.write_card()
phone.control()print(phone.producer)

4.2.2 pass关键字

  • pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思

pass 的主要用途包括:

  1. 占位符:当在开发过程中正在编写框架或者计划添加代码逻辑但还没有完成时,可以使用 pass 来避免语法错误。

  2. 空函数或类:定义一个函数或类,但是暂时没有需要放入其中的代码。这时可以使用 pass 来定义一个空函数或空类。

示例:

# 占位符示例
if some_condition:pass  # 以后填充条件的实际逻辑# 定义空函数
def empty_function():pass  # 暂时没有函数体,之后可能添加逻辑# 定义空类
class EmptyClass:pass  # 暂时没有类的成员,之后可能添加属性和方法

4.2.3 多继承注意事项

  • 多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即:先继承的保留,后继承的被覆盖
  • 这个概念被称为"方法解析顺序"(Method Resolution Order,简称MRO)。Python使用C3线性化算法来计算MRO,以确定调用同名成员时的优先级。
class A:def show(self):print("A")class B:def show(self):print("B")class C(A, B):passclass D(B, A):passobj1 = C()
obj2 = D()obj1.show()  # 输出: A,因为 A 在 C 的继承列表的左边
obj2.show()  # 输出: B,因为 B 在 D 的继承列表的左边

4.2.4 复写

  • 在面向对象编程中,子类可以通过复写(覆盖)父类的成员(方法或属性)来改变其行为。当子类定义了与父类同名的方法或属性时,子类的成员会覆盖父类的成员,从而在子类的实例中执行子类自己的逻辑。

示例:

class Animal:def speak(self):print("Animal speaks")class Dog(Animal):def speak(self):print("Dog barks")class Cat(Animal):def speak(self):print("Cat meows")animal = Animal()
dog = Dog()
cat = Cat()animal.speak()  # 输出: Animal speaks
dog.speak()     # 输出: Dog barks
cat.speak()     # 输出: Cat meows

4.2.5 调用父类同名成员

  • 一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员。如果需要使用被复写的父类的成员,需要特殊的调用方式:
    方式1:
  • 调用父类成员
    • 使用成员变量:父类名.成员变量
    • 使用成员方法:父类名.成员方法(self)

方式2:

  • 使用super()调用父类成员
    • 使用成员变量:super().成员变量
    • 使用成员方法:super().成员方法()

以下是一个调用父类方法的示例:

class Vehicle:def start(self):print("Vehicle started")class Car(Vehicle):def start(self):super().start()  # 调用父类方法print("Car started")car = Car()
car.start()

输出:

Vehicle started
Car started

  • 只能在子类内调用父类的同名成员,子类的类对象直接调用会调用子类复写的成员

  • 当子类复写了父类的成员(方法或属性),在子类内部可以通过 super() 函数来调用父类的同名成员。这是因为子类复写后,父类的成员被覆盖,但如果希望在子类中使用父类的实现,可以使用 super() 来实现这一点。

  • 然而,在子类的类对象直接调用成员时,会调用子类自己复写的成员。这是因为类对象直接访问成员时,不会触发 super() 的机制,而是直接使用类对象中的成员。

示例:

class Animal:def speak(self):print("Animal speaks")class Dog(Animal):def speak(self):print("Dog barks")class Cat(Animal):def speak(self):print("Cat meows")dog = Dog()
cat = Cat()dog.speak()  # 输出: Dog barks
cat.speak()  # 输出: Cat meows# 类对象调用
Dog.speak()  # 输出: Dog barks
Cat.speak()  # 输出: Cat meows
  • 通过实例(对象)调用 speak() 方法时,会根据对象的类型调用相应的方法。但是,当您通过类对象直接调用 speak() 方法时,将会根据类对象的定义来调用方法,而不会触发 super() 机制。这导致了子类自己复写的方法被调用。

4.3 类型注解

  • Python在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。
  • 类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)。它不会影响程序的实际执行,但可以提供更好的代码可读性、静态分析和类型检查。
  • 类型注解使用PEP 484中定义的语法规则
    主要功能:
  • 帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示
  • 帮助开发者自身对变量进行类型注释

支持:

  • 变量的类型注解
  • 函数(方法)形参列表和返回值的类型注解

4.3.1 变量的类型注解

基础语法:

变量: 类型
  • 类型注解的一些常见用法:
  1. 变量注解
    x: int = 5
    name: str = "Alice"
    
  2. 容器类型注解
    • 元组类型设置类型详细注解,需要将每一个元素都标记出来
    • 字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value
    # 基础容器类型注解
    my_list: list = [1, 2, 3]
    my_tuple: tuple = (1, 2, 3)
    my_dict: dict = {"itheima": 666}# 容器类型详细注解
    my_list: list[int] = [1, 2, 3]
    my_tuple: tuple[int, str, bool] = (1, "itheima", True)
    my_dict: dict[str, int] = {"itheima": 666}
    
  3. 在注释中添加类型注解
    # 在注释中进行类型注解
    var_1 = random.randint(1, 10)   # type: int
    var_2 = json.loads('{"name": "zhangsan"}')  # type: dict[str, str]
    def func():return 10
    var_3 = func()  # type: int
    
    • 尽管这种方式在早期版本的Python中是一种常见的做法,但它并不是官方推荐的类型注解方式,因为它不会被类型检查工具如mypy等识别和解析。官方推荐的类型注解方式是使用PEP 484中定义的语法规则。
  • 官方推荐的类型注解方式
    from typing import Dictvar_1: int = random.randint(1, 10)
    var_2: Dict[str, str] = json.loads('{"name": "zhangsan"}')def func() -> int:return 10var_3: int = func()
    

4.3.2 函数(方法)的类型注解

  • 函数和方法的形参类型注解语法:
    def 函数方法名(形参名:类型,形参名:类型)内容体
    
  • 函数(方法)的返回值类型注解的语法
def 函数方法名(形参名:类型,形参名:类型)->返回值类型内容体

  • 演示:
  1. 函数参数注解
def greet(name: str) :print f"Hello, {name}"
  1. 函数返回值注解
def add(a: int, b: int) -> int:return a + b
  1. 复杂数据类型注解
from typing import List, Tupledef process_data(data: List[Tuple[str, int]]) -> List[str]:result = [f"{name}: {value}" for name, value in data]return result

4.2.3 Optional和Union类型

  • Optional 和 Union 是用于类型注解中表示可选值或多种可能类型的重要工具
    • Optional用于表示一个值可以是特定类型,也可以是None。这在函数参数和返回值注解中特别有用,因为它允许参数可以是指定的类型,也可以是None。
    • 使用Union[类型, ......, 类型]可以定义联合类型注解
    • Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用。
  1. Optional类型:表示可选的类型。
    • age参数可以是int类型,也可以是None
from typing import Optionaldef print_age(age: Optional[int]) -> None:if age is not None:print(f"Age: {age}")
  1. Optional和Union类型:表示多种可能的类型。
from typing import Union
def combine(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:return a + b

4.2.4 自定义类型

  • NewType 是 Python 的 typing 模块中的一个工具,用于创建新的、独特的类型别名。它用于为现有的基本数据类型创建更具有语义的新类型,以提高代码的可读性和类型检查。

在实际使用中,NewType 并不会引入新的数据结构或运行时类型检查,它只是为了在类型注解中提供更多的语义信息,以及帮助类型检查工具识别不同的类型别名。

  • 以下是使用 NewType 来自定义新的类型别名的示例:

    from typing import NewType# 使用 NewType 创建 UserId 类型
    UserId = NewType('UserId', int)def get_user_name(user_id: UserId) -> str:return f"User {user_id}"
    
    • 在这个例子中,通过 NewType 创建了一个新的类型 UserId,它是一个整数 (int) 的别名。尽管 UserId 在类型注解中使用起来与 int 类型一样,但它有助于代码的可读性和类型检查。类型检查工具会将 UserId 视为不同于普通 int 的类型,从而提高了代码的安全性和可维护性。
  • 注意,NewType 不会在运行时引入额外的开销,因为它只是在类型注解中添加了更多的信息。在类型检查工具中,它可以帮助捕获一些潜在的类型错误。

4.2.5 补充:PEP 484中定义的语法规则

PEP 484定义了Python中类型注解的语法规则。以下是一些重要的语法规则和概念:

  1. 基本类型注解:使用内置的基本数据类型来进行注解,如intfloatstr等。

    x: int = 5
    name: str = "Alice"
    
  2. 复杂数据类型注解:使用typing模块中的类型来注解复杂数据类型,如ListTupleDict等。

    from typing import List, Tupledef process_data(data: List[Tuple[str, int]]) -> List[str]:result = [f"{name}: {value}" for name, value in data]return result
    
  3. 函数参数和返回值注解:使用->箭头表示函数的返回值类型注解。

    def add(a: int, b: int) -> int:return a + b
    
  4. Optional 和 Union 类型:使用Optional表示一个可选的类型,使用Union表示多种可能的类型。

    from typing import Optional, Uniondef print_age(age: Optional[int]) -> None:if age is not None:print(f"Age: {age}")def combine(a: Union[int, float], b: Union[int, float]) -> Union[int, float]:return a + b
    
  5. Type Aliases(类型别名):使用TypeVar来创建泛型类型参数,使用NewType来创建自定义的类型别名。

    from typing import TypeVar, NewTypeT = TypeVar('T')def repeat_item(item: T, times: int) -> List[T]:return [item] * timesUserId = NewType('UserId', int)
    
  • PEP 484中定义的一些基本语法规则,允许你为变量、函数参数和返回值添加类型注解,从而提高代码的可读性和可维护性。
  • 类型注解并不会影响程序的实际执行,但可以在编辑器、IDE和类型检查工具中提供更好的代码分析和错误检测。

五 多态

5.1 多态概念

在这里插入图片描述

  • 多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。
  • 多态常作用在继承关系上。比如:函数(方法)形参声明接收父类对象,实际传入父类的子类对象进行工作。即:以父类做定义声明,以子类做实际工作,用以获得同一行为, 不同状态
class Animal:def speak(self):passclass Dog(Animal):def speak(self):print("汪汪汪")class Cat(Animal):def speak(self):print("喵喵喵")def make_noise(animal: Animal):"""制造点噪音,需要传入Animal对象"""animal.speak()# 演示多态,使用2个子类对象来调用函数
dog = Dog()
cat = Cat()make_noise(dog) # "汪汪汪"
make_noise(cat) # "喵喵喵"

5.2 抽象类(接口)

  • 父类Animal的speak方法,是空实现
    这种设计的含义是:
    • 父类用来确定有哪些方法
  • 具体的方法实现,由子类自行决定
  • 这种写法,就叫做抽象类(也可以称之为接口)

抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass)称之为抽象方法
在这里插入图片描述

  • 抽象类的抽象方法子类必须实现
# 演示抽象类
class AC:def cool_wind(self):"""制冷"""passdef hot_wind(self):"""制热"""passdef swing_l_r(self):"""左右摆风"""passclass Midea_AC(AC):def cool_wind(self):print("美的空调制冷")def hot_wind(self):print("美的空调制热")def swing_l_r(self):print("美的空调左右摆风")class GREE_AC(AC):def cool_wind(self):print("格力空调制冷")def hot_wind(self):print("格力空调制热")def swing_l_r(self):print("格力空调左右摆风")def make_cool(ac: AC):ac.cool_wind()midea_ac = Midea_AC()
gree_ac = GREE_AC()make_cool(midea_ac)
make_cool(gree_ac)

六 进阶内容

使用对象组织数据

  • 在Python中,使用对象来组织数据,以便更好地管理和操作复杂的信息。对象允许将相关数据和方法封装在一起,使得代码更加模块化、可维护和可扩展。

1. 创建自定义类

  • 通过创建自定义类,定义一个新的数据类型,以适应应用程序的需求。这个类可以包含属性和方法,用于描述和操作该数据类型。
class Student:def __init__(self, name, age, grade):self.name = nameself.age = ageself.grade = gradedef get_info(self):return f"Name: {self.name}, Age: {self.age}, Grade: {self.grade}"# 创建学生对象
student1 = Student("Alice", 16, "10th")
student2 = Student("Bob", 17, "11th")# 访问对象的属性和方法
print(student1.get_info())  # 输出: Name: Alice, Age: 16, Grade: 10th
print(student2.get_info())  # 输出: Name: Bob, Age: 17, Grade: 11th

2. 数据结构的封装

使用对象来封装复杂的数据结构,例如列表、字典或其他对象,以创建更有结构的数据模型。

class ShoppingCart:def __init__(self):self.items = []def add_item(self, item):self.items.append(item)def calculate_total(self):total = 0for item in self.items:total += item['price']return total# 创建购物车对象
cart = ShoppingCart()# 添加商品
cart.add_item({'name': 'Apple', 'price': 1})
cart.add_item({'name': 'Banana', 'price': 0.5})# 计算总价
total_price = cart.calculate_total()
print(f"Total Price: ${total_price}")

3. 组合和关联

  • 将不同类型的对象组合起来,以表示更复杂的概念和关系。例如,一个学校对象可以包含多个学生对象。
class School:def __init__(self, name):self.name = nameself.students = []def add_student(self, student):self.students.append(student)def get_student_names(self):return [student.name for student in self.students]# 创建学校对象
school = School("ABC School")# 添加学生
school.add_student(student1)
school.add_student(student2)# 获取学生姓名列表
student_names = school.get_student_names()
print(f"Student Names: {student_names}")

4. 继承和多态

  • 通过继承和多态性,创建一个类层次结构,其中不同的类可以共享一些相似的属性和方法,并在需要时实现特定的行为。
class Animal:def speak(self):passclass Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"# 创建动物对象
dog = Dog()
cat = Cat()# 调用不同的 speak 方法
print(dog.speak())  # 输出: Woof!
print(cat.speak())  # 输出: Meow!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/61855.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka3.4 SASL/kerberos/ACL 证以及 SSL 加密连接

Kafka3.4 SASL/kerberos ACL 证以及 SSL 加密连接 序 前面我们使用 kafka3.3.1 on zookeeper 的模式进行多网段监听的 kafka 集群&#xff0c;顺便搭建起 kafkaui 后发现一些问题&#xff0c;我们 kafka 集群没有连接认证&#xff0c;万一谁知道了我们的 kafka 连接地址&…

java连接sqlserver细节处理

这个文章记录一下java连接sqlserver细节处理 &#xff0c;有其他的细节可以评论。 首先是 驱动 driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriverpom文件 将mysql的改成这个 <!-- 数据库驱动 --><dependency><groupId>com.microsoft.sqlserve…

[国产MCU]-BL602开发实例-定时器

定时器 文章目录 定时器1、BL602定时器介绍2、定时器驱动API介绍3、定时器使用实例3.1 单次计时3.2 持续计时通用定时器,用于定时,当时间到达我们所设置的定时时间会产生定时中断,可以用来完成定时任务。本文将详细介绍如何使用BL602的定时器功能。 1、BL602定时器介绍 BL6…

牛奶产业链的工业“链主品牌”利乐是如何诞生的?

瑞典的利乐公司&#xff0c;一个在乳品产业链中占据重要地位的“链主品牌”&#xff0c;通过提供创新的包装材料和解决方案&#xff0c;在全球范围内占据了显著的市场份额。利乐从不生产一滴奶&#xff0c;却赚取了中国乳业 75%的利润&#xff0c;一年创收超过 800 亿人民币。在…

bash: make: command not found

make之后报错信息如下&#xff1a;cd 对应的文件路径后 make 发现报错&#xff1a;bash: make: command not found 这个原因可能是没有安装make工具,也可能是安装了make之后,没有将make的文件路径添加到系统环境变量中 有没有安装make,可以使用Search Everything搜索是否有make…

数据结构-1

1.2 线性结构树状结构网状结构&#xff08;表 数 图&#xff09; 数据&#xff1a;数值型 非数值型 1.2.3数据类型和抽象数据类型 1.3抽象数据类型 概念小结&#xff1a; 线性表: 如果在独立函数实现的 .c 文件中需要包含 stdlib.h 头文件&#xff0c;而主函数也需要包含 st…

2023年市面上最受欢迎的工程项目管理软件推荐

随着科技的发展和工程项目的复杂性增加&#xff0c;工程项目管理软件成为了现代项目管理中不可或缺的工具。这些软件可以帮助团队更好地协调、组织和执行工程项目&#xff0c;并提高项目的效率和成功率。本文结合了不同的产品测评网站&#xff0c;总结了以下四款备受好评的工程…

ARTS 挑战打卡的第7天 --- Ubuntu中的WindTerm如何设置成中文,并且关闭shell中Tab键声音(Tips)

前言 &#xff08;1&#xff09;Windterm是一个非常优秀的终端神器。关于他的下载我就不多说了&#xff0c;网上很多。今天我就分享一个国内目前没有找到的这方面的资料——Ubuntu中的WindTerm如何设置成中文&#xff0c;并且关闭shell中Tab键声音。 将WindTerm设置成中文 &…

10 年 2023 大目标检测模型总结

对象检测示例 “物体检测是计算机视觉中最令人兴奋和最具挑战性的问题之一&#xff0c;深度学习已成为解决这一问题的有力工具。 — 陈良杰博士 OBJECT检测是计算机视觉中的一项基本任务&#xff0c;涉及识别和定位图像中的对象。深度学习彻底改变了对象检测&#xff0c;可以更…

分布式数据库视角下的存储过程

存储过程很好呀&#xff0c;那些用不好的人就是自己水平烂&#xff0c;不接受反驳&#xff01;我就有过这样念头&#xff0c;但分布式数据库&#xff0c;更倾向少用或不用存储过程。 1 我从C/S时代走来 C/S架构时代的末期最流行开发套件是PowerBuilder和Sybase数据库&#xf…

虚幻引擎游戏开发过程中,游戏鼠标如何双击判定?

UE虚幻引擎对于游戏开发者来说都不陌生&#xff0c;市面上有47%主机游戏使用虚幻引擎开发游戏。作为是一款游戏的核心动力&#xff0c;它的功能十分完善&#xff0c;囊括了场景制作、灯光渲染、动作镜头、粒子特效、材质蓝图等。本文介绍了虚幻引擎游戏开发过程中游戏鼠标双击判…

C#实现邮箱验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core Web API&#xff0c;163邮箱 1、在163邮箱的设置中开通IMAP/SMTP的服务&#xff0c;授权成功后会弹出一个窗体&#xff08;如下图所示&#xff09;&#xff0c;上面显示了授权密码…