Python魔法方法、特性、迭代器
参考《Python基础教程(第三版)》——Magnus Lie Hetland
0.构造函数
class FooBar():
def __init__(self,value = 42):
self.somevar = value
f = FooBar()
print(f.somevar)
f.somevar = 'This is a constructor argument'
print(f.somevar)
f_2 = FooBar('This is the same constructor in another item')
print(f_2.somevar)
>>>
======================= RESTART: D:\CSDN代码块\code_0.py =======================
42
This is a constructor argument
This is the same constructor in another item
>>>
可以将构造函数理解为创建实例化对象时调用的初始化函数,在对象生成的时候构造对象的相应属性。
设想: 在某些项目当中,如果构造函数属性较多,可以尝试使用字典形式,而非以为使用列表与索引值。
重写普通方法和特殊的构造函数:
class A:
def hello(self):
print('Hello,I\'m A')
class B(A):
pass
a = A()
b = B()
a.hello()
b.hello()
>>>
======================= RESTART: D:/CSDN代码块/code_1.py =======================
Hello,I'm A
Hello,I'm A
>>>
类B没有定义自己的hello方法,所以在调用时,打印的消息与类A相同。
class A:
def hello(self):
print('Hello,I\'m A')
class B(A):
def hello(self):
print('Hello,I\'m B')
a = A()
b = B()
a.hello()
b.hello()
>>>
======================= RESTART: D:\CSDN代码块\code_2.py =======================
Hello,I'm A
Hello,I'm B
>>>
重写是继承机制的一个重要方面,对构造函数尤其重要。
有时候,重写构造函数时要调用超类的构造函数,否则无法正确初始化对象。
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaah...')
self.hungry = False
else:
print('No,thanks!')
class SongBird(Bird):
def __init__(self):
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
>>> sb = SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
sb.eat()
File "D:/CSDN代码块/code_3.py", line 5, in eat
if self.hungry:
AttributeError: 'SongBird' object has no attribute 'hungry'
>>>
异常中明确指出,构造函数当中缺少名为hungry的属性。
为此有两种方法:调用未关联的超类构造函数,以及使用函数super()
1.调用未关联的超类构造函数
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
>>> sb = SongBird()
>>> sb.eat()
Aaaah...
>>> sb.eat()
No,thanks!
>>>
2.使用函数super
class SongBird(Bird):
def __init__(self):
super().__init__()
self.sound = 'Squawk!'
def sing(self):
print(self.sound)
>>> sb = SongBird()
>>> sb.eat()
Aaaah...
>>> sb.eat()
No,thanks!
>>>
使用super函数的优点
super函数更直观,同时即便有多个超类,也只需调用函数super一次(前提是所有超类的构造函数也使用super)。
元素访问
1.__ len __(self)
这个方法应返回集合包含的项数,对序列来说为元素个数,对映射来说为键值对数,如果__len__()返回零,且没有实现覆盖这种行为的__nonzero__(),则在布尔上下文中视为假(False)
2.__ getitem __(self,key)
这个方法应返回与指定键相关联的值,对序列来说,0 <= key <= n-1,其中n为序列长度。对映射来说键可以为任何类型。
3.__ setitem __(self,key,value)
这个方法应以键相关联的方式存储值,以便以后能够使用__getitem__()来获取,当然,仅当对象可变时才需要实现这个方法。
4.__ delitem __(self,key)
这个方法在对对象的组成部分使用__del__语句时被调用,应删除与key相关联的值。同样,仅当对象可变(且允许其被删除)时,才需要实现这个方法。
def check_index(key):
if not isinstance(key,int):raise TypeError
if key < 0:raise IndexError
class ArithmeticSequence:
def __init__(self,start = 0,step = 1):
self.start = start
self.step = step
self.changed = {}
def __getitem__(self,key):
check_index(key)
try:return self.changed[key]
except KeyError:
return self.start + key * self.step
def __setitem__(self,key,value):
check_index(key)
self.changed[key] = value
>>> a = ArithmeticSequence(1,3)
>>> a[3]
10
>>> a[18]
55
>>> len(a)
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
len(a)
TypeError: object of type 'ArithmeticSequence' has no len()
>>> del a[2]
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
del a[2]
AttributeError: __delitem__
>>>
以上代码实现的是一个算术序列,设置参数以构成等差数列。这个序列长度无穷,允许用户对其中的值进行修改