python基础(9):构造函数


构造函数

注意:
       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 问题

  1. self 在定义类的方法时是必须有的?
  2. 构造函数的定义中必须带有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.重构构造函数

构造函数用于初始化新建对象的状态,而对大多数子类来说,除超类的初始化代码外,还需要有自己的初始化代码。

注意:

  1. 如果子类显式定义了自己的构造函数,那么实例化的时候,调用的是自己的构造函数,否则,调用的是父类
>>> 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
  1. 重写构造函数时,必须调用超类(继承的类)的构造函数,否则可能无法正确地初始化对象,即:没有完整继承父类。——当你调用了父类的某个方法,而这个方法使用到了父类构造方法中才定义的变量的时候,会发生错误。
 >>> 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
       问题
  1. super() 和 直接调用父类的构造函数的区别

[ 参考文档 ]

  • [挪]-Magnus-Lie-Hetland-Python基础教程(第3版)
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值