今天正好看到了python中构造函数这点东西,有所感悟,记录下来,备忘。python中的构造函数被原作者称之为magic methods,也是比较的神奇,但是跟C++中的构造函数相差不是很多,虽然说法不同,但是很是有很多相同之处的。接触过,有准备了也就能更加清楚了。C++ 当中的继承也需要对构造函数进行传参,初始化。所以python中的代码也是很类似。
先看一个比较简单的例子:全文代码中的注释都需要去掉之后才能运行
class bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaaaah ')
self.hungry = False
else:
print('No,Thanks!')
b = bird()
b.eat()
b.eat()
输出:
Aaaaaah
No,Thanks!
[Finished in 0.1s]
这个还是比较容易理解的,比较的简单,下面我新建一个类Songbird,继承bird中的属性,得到新的技能sing
class bird: #基类
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaaaah ')
self.hungry = False
else:
print('No,Thanks!')
class Songbird(bird):#派生类,继承了bird
def __init__(self):
self.sound='Squawl'
def sing(self):
print self.sound
sb = Songbird();
b = bird()
b.eat()
b.eat()
sb.sing()
输出结果:
Aaaaaah
No,Thanks!
Squawl
[Finished in 0.1s]
这个其实也没啥,就是简单的继承和派生,从基类中继承到了东西,然后使用。所以下面才是重点:
class bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaaaah ')
self.hungry = False
else:
print('No,Thanks!')
class Songbird(bird):
def __init__(self):
self.sound='Squawl'
def sing(self):
print self.sound
sb = Songbird();
b = bird()
b.eat()
b.eat()
sb.sing()
sb.eat()
这段代码运行的时候就出现了错误,运行结果如下:
Aaaaaah
No,Thanks!
Squawl
Traceback (most recent call last):
File "E:\Sublime\1.py", line 20, in
sb.eat()
File "E:\Sublime\1.py", line 5, in eat
if self.hungry:
AttributeError: Songbird instance has no attribute 'hungry'
[Finished in 0.1s with exit code 1]
也就是说我们前面都可以,但是到了调用基类中的eat()函数时,提示错误,这就是我们C++中也经常遇到的问题,其实就是派生类在继承的时候,对基类的构造函数未初始化。
有两种方法来实现目标:
1调用超类构造方法的未绑定版本
class bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaaaah ')
self.hungry = False
else:
print('No,Thanks!')
class Songbird(bird):
def __init__(self):
bird.__init__(self)
self.sound='Squawl'
def sing(self):
print self.sound
sb = Songbird();
b = bird()
b.eat()
b.eat()
sb.sing()
sb.eat()
输出结果:
Aaaaaah
No,Thanks!
Squawl
Aaaaaah
[Finished in 0.1s]
为什么这次可以呢,以为在调用一个实例的时候,该方法的self参数会自己绑定到实例上(这就是绑定方法),但是直接调用类的方法,例如(Bird__init__),就没有实例与之绑定,这时候就需要一个self参数,提供一个self参数,这样的方法就称之为未绑定(unbound)
2.使用super函数。
当前的类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类(也就是基类)的方法,而不是当前类的方法。
class bird(object):
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('Aaaaaah ')
self.hungry = False
else:
print('No,Thanks!')
class Songbird(bird):
def __init__(self):
super(Songbird, self).__init__()
self.sound='Squawl'
def sing(self):
print self.sound
sb = Songbird();
b = bird()
b.eat()
b.eat()
sb.sing()
sb.eat()
输出结果:
Aaaaaah
No,Thanks!
Squawl
Aaaaaah
[Finished in 0.1s]
这结果跟之前的方法输出结果是相同的,但是更加直观,更方便。