面向对象¶
类型¶
isinstance(<object>, <type>):测试对象是否是某种类型type(<object>):返回对象的类型
类 (Class)¶
定义了特定类型的对象如何行为的模板或蓝图
对象包含数据和行为。class 关键字用于定义类,类是对象的一种形式。所有值都是一种对象。
代码实现:
class ClassName:
def __init__(self, 参数):
# 初始化属性
self.属性 = 参数
def 方法(self, 参数):
# 方法实现
attr = 1 # 创建类的属性
对象 (Object)¶
类的实例 (Instance);类是该对象的类型。创建实例可以使用类名加括号的形式:obj = ClassName(参数),这会调用类的 __init__ 方法来初始化对象。
方法¶
方法可以看作是在对象上调用的函数
调用:对象.方法(参数)
调用时,Python 会将对象本身作为第一个参数传递给方法,通常命名为 self。
调用方法时,首先查找实例属性,如果在实例中没找到,系统会转而去该对象所属的类 (Class) 中寻找
getattr(<obj>, <name>[, <default>]):获取对象 <obj> 的属性 <name> 的值。如果属性不存在且提供了 <default>,则返回 <default>,否则引发 AttributeError。
对象.方法实际上是一个方法(当不加括号时,被评估为bound method)。可以把它赋值给另一个变量,然后通过该变量调用。而类.方法则是一个函数,需要传入实例对象作为第一个参数。
特殊方法¶
特殊方法(也称为魔术方法)是以双下划线开头和结尾的方法,是Python预定义的方法,但是也可以在类中自行修改,用于实现类的特定行为。例如:
__add__(self, other): 定义(左侧)加法运算符+的行为。__radd__(self, other): 定义右侧加法运算符+的行为。__bool__(self): 定义对象的布尔值,用于条件判断。__float__(self): 定义对象转换为浮点数的行为。__repr__(self): 定义对象的字符串表示。用repr()函数调用。__str__(self): 定义对象的用户友好字符串表示。用str()、print()、format()函数调用。
继承¶
类可以从另一个类继承属性和方法。子类继承父类的所有属性和方法,可以重写父类的方法以提供特定实现。满足is-a关系的类之间可以使用继承。例如:
class Parent:
def method(self):
# 父类的方法
class Child(Parent):
def method(self):
# 重写父类的方法
def __init__(self):
super().__init__() # super():找父类 __init__找父类的__init__函数 (<iter>)传入子类的参数
组合¶
通过在一个类中包含另一个类的实例来实现代码复用和功能扩展。满足has-a关系的类之间可以使用组合。例如:
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine()
def start(self):
self.engine.start()
print("Car started")
my_car = Car()
my_car.start()
更改¶
对于预先声明的可变对象,把它绑定到几个变量上,通过更改其属性或调用其方法来更改对象,不管更改是通过哪个变量进行的,所有变量都会反映出更改后的对象。
等同¶
- Identity(身份):
is ,如果两个变量引用同一个对象,则返回 True,否则返回 False。 - Equality(等值):
== ,如果两个变量引用的对象内容相同,则返回 True,否则返回 False。
对于赋值语句 <var> = <exp>,变量 <var> 可以代表 <exp> 计算结果的对象。
需要注意,等值不代表是同一个对象,例如 [10] is [10] 返回 False。
迭代器¶
迭代器是一个对象,它实现了迭代协议,即包含 iter() 和 next() 方法。迭代器用于遍历容器(如列表、元组、字典等)中的元素。例如:
如果在for循环中使用迭代器,Python会自动调用iter()和next()方法来遍历元素。但是这也会改变迭代器的状态,导致无法重复使用。
map(<func>, <iterable>)函数:返回一个迭代器对象,通过对传入的函数依次作用于序列的每个元素,生成新的元素。例如:map(str, [1, 2, 3]) 会返回一个迭代器,生成字符串 '1', '2', '3'。
reversed(<iterable>)函数:返回一个反向迭代的迭代器对象。例如:reversed([1, 2, 3]) 会返回一个迭代器,生成元素 3, 2, 1。
filter(<func>, <iterable>)函数:返回一个迭代器对象,通过对传入的函数依次作用于序列的每个元素,筛选出满足条件的元素。例如:filter(lambda x: x > 1, [1, 2, 3]) 会返回一个迭代器,生成元素 2, 3。
zip(<iterable1>, <iterable2>, ...)函数返回一个聚合了多个可迭代对象的迭代器对象。例如:zip([1, 2, 3], ['a', 'b', 'c']) 会返回一个迭代器,生成元组 (1, 'a'), (2, 'b'), (3, 'c')。
for 循环的“自动驾驶”模式
对于for循环:
- 获取迭代器:它首先调用生成器的 iter() 方法(生成器会返回它自己)。
- 自动迭代:它会自动反复调用 next() 来获取下一个值。
- 自动停止:当生成器运行结束(抛出 StopIteration 异常)时,for 循环会自动捕捉到这个信号并优雅地停止,而不会报错。
生成器¶
生成器是一种特殊类型的迭代器,通过使用 yield 语句定义。生成器函数在调用时不会立即执行,而是返回一个生成器对象,只有在迭代时才会执行函数体,并在每次遇到 yield 时暂停并返回一个值。例如:
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
counter = count_up_to(3)
print(next(counter)) # 输出: 1
print(next(counter)) # 输出: 2
print(next(counter)) # 输出: 3
yield from <iterable> 语句:用于在生成器函数中委托子生成器或可迭代对象。
包装器¶
repr(obj): 返回对象的字符串表示。
repr() 的实际执行过程:从实例调用 x.__repr__() 时,Python 会自动把 x 作为第一个参数(即 self)传进去;从类调用时,它是一个普通的函数(类中的函数)。因为它不知道要处理哪个具体的实例,所以必须手动把实例 x 传进去,即type(obj).__repr__(obj),相当于传入了self。
-
eval(obj):将对象看作代码执行。eval(repr(obj))通常会返回与obj相等的对象(repr()返回字符串,eval()执行)。 -
str(obj): 返回对象的用户友好字符串表示,适合打印输出查看。str()的实际执行过程是调用对象的__str__()方法。
例如:repr(Fraction(1, 3)) 返回 'Fraction(1, 3)',而 str(Fraction(1, 3)) 返回 '1/3'。repr,str是print()函数的输出
接口¶
接口是类对外提供的功能和行为的集合。通过定义清晰的接口,类可以隐藏其内部实现细节,只暴露必要的方法和属性给外部使用者。
消息传递(Message Passing): 对象之间通过查找属性(调用方法)来交互。向一个对象“发送消息”(调用它的方法),它给你回馈。
抽象的方法: 当不同的类(比如“分数类”和“复数类”)都拥有同名的属性或方法时,这就是一种抽象。
接口的本质: 接口是一组共享的消息(方法名)以及对这些消息含义的规定。