文章目录
构造函数
注意:
1. 构造函数将在对象创建后自动调用
它们。
2. 若没有显式定义(即自己创建一个)构造函数的话,默认会自动添加一个构造函数。
3. 类中除了构造函数,对应也有一个析构函数(destructor)
。这个方法在对象被销毁(作为垃圾被收集)前
被调用,但鉴于你无法知道准确的调用时间,建议尽可能不要使用__del__
。
1.创建构造函数
语句: def __init__
1.1 带self参数
>>> class FooBar:
... def __init__(self):
... self.somevar=42
...
>>> FooBar.somevar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'FooBar' has no attribute 'somevar'
>>> f=FooBar() # 即 自动调用构造函数__init__
>>> f.somevar
42
1.2 带有self和其他参数
>>> class FooBar:
#如果调用的时候:
# 1.有传入参数值,则value=参数值
# 2.没有传入参数值,则使用默认值,即:value=42
... def __init__(self,value=42):
... self.somevar=value
...
# 没有传入参数
>>> f=FooBar()
>>> f.somevar
42
# 传入了参数
>>> b=FooBar("This is a constructor argument")
>>> b.somevar
'This is a constructor argument'
♥1.3 问题
- self 在定义类的方法时是必须有的?
- 构造函数的定义中必须带有self参数吗?创建类的实例的时候,会自动传递实例作为参数?
>>> class FooBar:
... somevar=0
... def __init__():
... FooBar.somevar=1
...
>>> FooBar.somevar
0
>>> f=FooBar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 0 positional arguments but 1 was given
2.重构构造函数
构造函数用于初始化新建对象的状态,而对大多数子类来说,除超类的初始化代码外,还需要有自己的初始化代码。
注意:
- 如果子类
显式定义了自己的构造函数
,那么实例化的时候,调用的是自己的构造函数
,否则,调用的是父类
>>> class FooBar:
... def __init__(self):
... print("I'm FooBar")
...
# 1.子类定义了自己的构造函数,即重写构造函数
>>> class Child(FooBar):
... def __init__(self):
... print("I'm Child")
...
>>> c=Child() #调用自己的构造函数
I'm Child
# 2.子类没有定义自己的构造函数
>>> class Child(FooBar):
... pass
...
>>> c=Child() #调用父类的构造函数
I'm FooBar
- 重写构造函数时,
必须调用超类(继承的类)的构造函数,否则可能无法正确地初始化对象,即:没有完整继承父类。
——当你调用了父类的某个方法,而这个方法使用到了父类构造方法中才定义的变量的时候,会发生错误。
>>> class Bird:
... def __init__(self):
... self.hungry=True
... def eat(self):
... if self.hungry:
... print("Aaaah ...")
... self.hungry=False
... else:
... print("No,thanks")
... def sleep(self):
... print("I will go to sleep")
...
>>> class SongBird(Bird):
... def __init__(self):
... self.sound="Squawk!"
... def sing(self):
... print(self.sound)
...
>>> sb=SongBird()
>>> sb.sing()
Squawk!
>>> sb.sleep()
I will go to sleep #调用父类的sleep()成功
>>> sb.eat()
Traceback (most recent call last): #调用父类的eat()失败
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in eat
AttributeError: 'SongBird' object has no attribute 'hungry'
2.1 调用父类的构造方法有两种方式
♠ 1.直接调用父类构造函数
♠ 2.使用函数super()
>>> class Bird:
... def __init__(self):
... self.hungry=True
... def eat(self):
... if self.hungry:
... print("Aaaah ...")
... self.hungry=False
... else:
... print("No,thanks")
... def sleep(self):
... print("I will go to sleep")
# 1.直接调用父类的构造方法
>>> class SongBird(Bird):
... def __init__(self):
... Bird.__init__(self)
... self.sound="Squawk!"
... def sing(self):
... print(self.sound)
...
>>> sb=SongBird()
>>> sb.sing()
Squawk!
>>> 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.sing()
Squawk!
>>> sb.eat()
Aaaah ...
>>> sb.eat()
No,thanks
♥ 问题
- super() 和 直接调用父类的构造函数的区别
[ 参考文档 ]
- [挪]-Magnus-Lie-Hetland-Python基础教程(第3版)