Python的构造方法:__init__() 详解

很多初学者在学习Python的面向对象部分时,不理解__init__()究竟是什么意思,我在这里做统一的回答。

创建一个类时,需要对类设置很多的实例字段(这里的“字段”实际上就是我们平时所说的“属性”。这里是为了区别属性与属性函数,故我引用了C#或Java中“字段”的说法),如下:

代码段_1

class Ball:
    pass
ball = Ball()

ball.color = 'red'
ball.size = 'small'
ball.direction = 'up'
#注意,以上字段是实例的字段,而非类的字段
print(ball.color)
print(ball.size)
print(ball.direction)

我们看到,class Ball:里面的代码是空着的,直接在外面对实例字段进行赋值。

这样肯定略显繁琐。在面向对象领域,有一个专门的工具做这件事情,叫做“构造器”,也叫做“构造方法”,“构造函数”,如下:

代码段_2

class Ball:
    def __init__(self,color,size,direction):
        #构造方法的本质是个函数。既然是函数,就满足函数和函数参数的一切性质
        self.color = color
        self.size = size
        self.direction = direction

ball = Ball('red','small','up')


print(ball.color)
print(ball.size)
print(ball.direction)

运行结果与代码段_1一致。

self是代码段_1中的ball的代名词。如果Ball类生成了很多实例,如ball_1,ball_2...那么,self就是ball、ball_1、ball_2的代名词。

self,英文意为“本身”。在Python中,即类本身创建的实例。

事实上,在Python的语法中,写“self”这个单词不是规定的,写任何单词都可以。例如C#或Java的程序员可以习惯用“this”,因为“this”是C#、Java规定的关键字。如果C#、Java程序员不太习惯Python的“self”,在写Python代码的时候,完全可以把“self”换成“this”。但是“self”是前辈们在这么多年使用Python中,约定俗成的“关键字”。为了Python代码的可读性和“业内习惯”,建议大家还是规规矩矩地写“self”。

注意,ball是ball,ball不是self,但是,self可以是ball。当然,self还可以是ball_1。所以,self包括了所有的实例。self和一个具体的实例是一种充分不必要的关系。

而且,方法参数里有了“self”,即说明该方法只能被类的实例所调用。而不能被类所调用。

当进行了类的实例化ball = Ball('red','small','up'),__init__()方法被添加了实际位置参数'red','small','up',然后自动运行。从某种意义上说('red','small','up')就是调用了__init__()方法的标志。所以,__init__()方法不需要额外使用实例去专门调用它。如:

ball.__init__('green','big','down')

没有必要再去用实例专门调用该方法。

但是,如果在必要的情况下,这种专门调用构造方法的语句还是需要的。

如:

class Ball:
    def __init__(self,color,size,direction):
        #构造方法的本质是个函数。既然是函数,就满足函数和函数参数的一切性质
        self.color = color
        self.size = size
        self.direction = direction

ball = Ball('red','small','up')#第一次调用了__init__()方法

print(ball.color)
print(ball.size)
print(ball.direction)

ball.__init__('green','big','down')#第二次调用了__init__()方法

print(ball.color)
print(ball.size)
print(ball.direction)

====================================================================================

下面,我们尝试将实例字段转化为类字段:

class Ball:
    pass
ball = Ball()

Ball.color = 'red'
Ball.size = 'small'
Ball.direction = 'up'
#现在,这些字段是类字段,而不是实例字段了

print(Ball.color)
print(Ball.size)
print(Ball.direction)

 我们前面说了,self指的是类的所有实例。现在,我们所要赋值的不再是实例的字段,而是类的字段。那么,对于类的字段,我们要使用构造方法,该怎么做呢?可以这么做:

class Ball:
    @classmethod
    def __init__(cls,color,size,direction):
        cls.color = color
        cls.size = size
        cls.direction = direction

ball = Ball('red','small','up')

print(Ball.color)
print(Ball.size)
print(Ball.direction)

很明显,我们把原来代码段的“self”换成了“cls”,还在方法前面加了一个修饰器“@classmethod”,代表这是一个类方法。

cls和self一样,不是Python规定的关键字,写任何关键字都可以。但是为了Python的可读性和业内规范,还是建议大家写“cls”。

============================================================================================

但是,在上一个代码段,我们有了Ball.color、Ball.szie、Ball.direction,那么ball.color、ball.szie、ball.direction是否存在呢?

答案是:存在的。返回的结果和Ball.color、Ball.szie、Ball.direction完全相同。

具体原因,请读者看我的另外一篇文章:《关于python的类成员、实例成员、静态成员的对比与联系》

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值