- 构造函数
在python中,创建构造函数和容易,只需将方法init的名称从普通的init改为魔法版__init__即可.
1 class FooBar: 2 def __init__(self): 3 self.somevar= 42 4 f = FooBar() 5 a = f.somevar 6 print(a)
执行结果
给构造函数添加几个参数
1 class FooBar: 2 def __init__(self, value = 42): 3 self.somevar= value 4 f = FooBar() 5 a = f.somevar 6 print(a)
执行结果
指定参数
1 class FooBar: 2 def __init__(self, value = 42): 3 self.somevar= value 4 f = FooBar(‘he he xiaoming‘) 5 a = f.somevar 6 print(a)
执行结果
- 重写普通方法和特殊的构造函数
类A定义了一个名为hello的方法,并被类B继承.
1 class A: 2 def hello(self): 3 print("Hello, I‘m A.") 4 class B(A): 5 pass 6 a = A() 7 b = B() 8 a.hello() 9 b.hello()
执行结果
B重写方法hello
1 class A: 2 def hello(self): 3 print("Hello, I‘m A.") 4 class B(A): 5 def hello(self): 6 print("Hello, I‘m B.") 7 a = A() 8 b = B() 9 a.hello() 10 b.hello()
执行结果
这个类定义了所有鸟都具备的一种基本能力:进食。从这个示例可知,鸟进食后就不在饥饿
1 class Bird: 2 def __init__(self): 3 self.hungry = True 4 def eat(self): 5 if self.hungry: 6 print(‘Aaaah...‘) 7 self.hungry = False 8 else: 9 print(‘NO, thanks!‘) 10 b = Bird() 11 b.eat() 12 b.eat()
执行结果
子类SongBird,它新增了鸣叫功能
1 class Bird: 2 def __init__(self): 3 self.hungry = True 4 def eat(self): 5 if self.hungry: 6 print(‘Aaaah...‘) 7 self.hungry = False 8 else: 9 print(‘NO, thanks!‘) 10 class SongBird(Bird): 11 def __init__(self): 12 self.sound = ‘Squakw!‘ 13 def sing(self): 14 print(self.sound) 15 sb = SongBird() 16 sb.sing()
执行结果
SongBird是Bird的子类,继承了方法eat,如果你尝试调用它,将发现一个问题.
1 class Bird: 2 def __init__(self): 3 self.hungry = True 4 def eat(self): 5 if self.hungry: 6 print(‘Aaaah...‘) 7 self.hungry = False 8 else: 9 print(‘NO, thanks!‘) 10 class SongBird(Bird): 11 def __init__(self): 12 self.sound = ‘Squakw!‘ 13 def sing(self): 14 print(self.sound) 15 sb = SongBird() 16 sb.sing() 17 sb.eat()
执行结果
异常清楚地指出了在什么地方:SongBird没有属性hungry,因为在SongBird中重写了构造函数,担心的构造函数没有包含任何初始化属性hungry的代码.
要消除这种错误,SongBird的构造函数必须调用其超类(Bird)的构造函数,以确保基本的初始化得以执行。为此,有两种方法:调用未关联的超类构造函
数,以及使用函数super。
- 调用未关联的超类构造函数
在SongBird类中,只添加了一行,其中包含代码Bird.__init__(self).对实例用方法时,方法的参数self将自动关联到实例(称为关联的方法)。然而,
如果你通过类调用方法(如Bird.__init__),就没有实例与其相关联。在这种情况下,你可随便设置参数self.这样的方法称为未关联的。
1 class Bird: 2 def __init__(self): 3 self.hungry = True 4 def eat(self): 5 if self.hungry: 6 print(‘Aaaah...‘) 7 self.hungry = False 8 else: 9 print(‘NO, thanks!‘) 10 class SongBird(Bird): 11 def __init__(self): 12 Bird.__init__(self) 13 self.sound = ‘Squakw!‘ 14 def sing(self): 15 print(self.sound) 16 sb = SongBird() 17 sb.sing() 18 sb.eat()
执行结果
- 使用函数super
如果你使用的不是旧版python,就应使用函数super.这个函数只是用于新式类。调用这个函数时,将当前类和当前实例作为参数。对其返回的对象调用方法
时,调用的将是超类(而不是当前类)的方法。因此,在songBird的构造函数中,可不适用Bird,而是shiyongsuper(SongBird,self)。
1 class Bird: 2 def __init__(self): 3 self.hungry = True 4 def eat(self): 5 if self.hungry: 6 print(‘Aaaah...‘) 7 self.hungry = False 8 else: 9 print(‘NO, thanks!‘) 10 class SongBird(Bird): 11 def __init__(self): 12 super().__init__() 13 self.sound = ‘Squakw!‘ 14 def sing(self): 15 print(self.sound) 16 sb = SongBird() 17 sb.sing() 18 sb.eat() 19 sb.eat()
执行结果
- 基本的序列和映射协议
- __len__(self): 这个方法应返回集合包含的项数,对序列来说为元素个数,对映射来说为键-值对数。如果__len__返回零(且没有实现覆盖这种行为的__nonzero__),对象在布尔上下文中将被视为假(就像空的列表、元组、字符串和字典一样)
- __getitem__(self, key):这个方法应返回与指定键相关联的值。对序列来说,键应该是0~n - 1的整数(也可以是负数),其中n为序列的长度。对映射来说,键可以使任何类型。
- __setitem__(self, key, value):这个方法应以与键相关联的方式存储值,以便以后能够使用__getitem__来获取。当然,仅当对象可变是才需要实现这个方法。
- __delitem__(self, key):这个方法在对对象的组成部分使用__del__语句时被调用,应删除与key相关联的值。同样,仅当对象可变(且允许其项被删除)时,才需要实现这个方法。
对于这些方法,还有一些额外的要求。
1. 对于序列:如果键为负整数,应从末尾往前数。换而言之,x[-n]应与x[len(x)-n]等效。
2.如果键的类型不合适(如对序列使用字符串键),可能引发TypeError异常。
3.对于序列,如果索引的类型是正确的,但不在允许的范围内,应引发IndexError异常。