python什么时候要构造方法init_构造方法——魔法方法1__init__()

构造方法也是函数,但是它调用的时间是确定的,当一个对象被创建之后,会立即调用构造方法。

原来我在写objective-c和C#时都会写构造方法,用来初始化类中属性。而且需要显示的调用。

Python中有一类魔法方法(特殊方法),初始化用到是init。

class Person:

def __init__(self):

self.name = "nzh"

self.age = 25

p1 = Person()

print("p1的姓名:{0},年龄:{1}".format(p1.name, p1.age))

image.png

在init函数中,我们设定了两个属性,name和age。并且直接赋值。

在调用Person()函数时,它会隐式调用init()函数,然后Person类的对象中的属性就被设置了。

init()函数中默认会传递一个self的参数,self代表的是对象自己,那么生成p1对象时调用的Person()函数时,这个self就代表了p1,self会对当前对象进行绑定。

上面的例子我们是把属性值都定死了,这不够灵活。如果想让自定义属性的值,就需要给init()函数传递参数。

# 构造一个用户信息

class User:

def __init__(self, name, age):

self.name = name

self.age = age

user1 = User("nzh", 25)

print("user1用户的名字:{0},年龄:{1}".format(user1.name, user1.age))

Python中有一个魔法方法叫del,相当于析构函数,它的作用是在被垃圾回收之前调用,但是发生的时间不可预知,应该尽力避免使用。

构造方法在继承中的使用

现在有两个类,A和B。B是A的子类。

A中定义了一个hello方法,B中没有定义任何内容,当B的对象调用hello方法时,同样可以调用。因为hello方法是从父类A中继承过来的。

这里面跟构造函数有很大关系,因为B的构造方法调用了A的构造方法,如果不是这样,B中就不能调用hello方法。

那么如何调用父类的构造方法?有两种方式。

调用未绑定的超类构造方法

在Python3.0之前会用到的方法,现在更流行用super函数,稍后说super,先说未绑定。

class Bird():

def __init__(self):

self.hungry = True

def eat(self):

if self.hungry == True:

print("吃点东西...")

self.hungry = False

else:

print("我不饿,谢谢")

class SongBird(Bird):

def __init__(self):

self.sound = "this is a song"

def sing(self):

print(self.sound)

s = SongBird()

s.sing()

s.eat()

image.png

这里SongBird类的对象不能调用eat方法,就是因为在SongBird初始化的时候没有调用超类的构造方法,可以修改SongBird的初始化函数init()

class SongBird(Bird):

def __init__(self):

Bird.__init__(self)

self.sound = "this is a song"

def sing(self):

print(self.sound)

加了一句Bird.init(self)就能调用了Bird类中的eat方法了?背后发生了一些事情。

在调用一个实例的方法时,该方法的self参数会被自动绑定到实例上(这叫绑定方法)。如果只是调用Bird.init(),而没有给它传递self参数,那么Bird也不知道绑定了哪个实例,而且会引发一个TypeError错误。

image.png

正如上图所示,错误信息显示init()方法少了一个必要的参数self。

如果直接调用Bird类的Bird.init呢?(看起来像是一个属性,而非方法)

image.png

同样可以看到,提示没有hungry属性,没有提供self参数,实例就不会被绑定,这样就可以随便提供self参数。

例子中是吧SongBird的self传给了Bird的init函数(不知道这么理解对不对),这种方法就是未绑定方法(unbound)

使用super函数

首先得知道super函数只能在新式类中使用,如果你使用过老版本的python那么就不行了。至少是2.2以后,因为super是2.2新加入的特性。

修改SongBird类:

class SongBird(Bird):

def __init__(self):

super(SongBird, self).__init__()

self.sound = "this is a song"

def sing(self):

print(self.sound)

为什么一个super就解决了这些问题呢?其实super函数很只能,不管你的这个类继承了多少层超类,它只需要使用一次super函数就可以调用超类中的方法,前提是这些超类中都要使用super函数。

super函数返回的是一个super对象,它负责对调用的方法进行解析,以至于我们可以成功调用超类中的方法。

有多层继承关系时,子类从下至上逐层寻找,比如D是C的子类,C是B的子类,B是A的子类。

那么继承关系就是这样的A->B->C->D。

D中先到C中找,如果C中没有该方法,再去B中找,最后再去A中找。找不到会报错,异常类型为AttributeError。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值