__init__(self),self,super,继承杂谈

Python 2.7
IDE Pycharm 5.0.3


  遇到问题,解决问题,才能不愧对自己花费的时间--小白语录

建议首先阅读:
@追梦的蜗牛果果–Python 继承之 self的解释
@LY_ysys629–python类class中_init_函数以及参数self的简单解释

  • class类包含:

类的属性:类中所涉及的变量
类的方法:类中函数

  • __init__函数(方法)

1.首先说一下,带有两个下划线开头的函数是声明该属性为私有,不能在类地外部被使用或直接访问。
2.init函数(方法)支持带参数的类的初始化 ,也可为声明该类的属性
3.init函数(方法)的第一个参数必须是 self(self为习惯用法,也可以用别的名字),后续参数则可 以自由指定,和定义函数没有任何区别。


OK,杂谈持续更新,想到哪写哪!有点模糊的概念自己理清一下,mark一下,先来个最基础的

# 首先,确定下这个self到底是个啥,这里self写成了this,可以写成任何你想的,只是约定俗成,规范起来写成self而已

>>> class Test:
...     def prt(this):
...         print(this)
...         print(this.__class__)
...
>>> t = Test()
>>> t
<__main__.Test instance at 0x103dd36c8>  # t是个instance
>>> t.prt()
<__main__.Test instance at 0x103dd36c8>
__main__.Test  # t的类是Test

ok,第二步

class A:
    def __init__(self,name='from init',age=0):
        self.name =name
        self.age =age

    def Me1(self,name_Me1='from Me1',age_Me1=1):
        print self.name,self.age
        self.name = name_Me1  # 这里进行重新的属性设置
        print self.name,self.age
        print name_Me1,age_Me1
        
a =A() # 用默认
a.Me1('不用默认',2)
print '------------'
b = A('重定义',3)
b.Me1() # 用默认  

from init 0
不用默认 0
不用默认 2
------------
重定义 3
from Me1 3
from Me1 1

这里解释下程序运行的过程,首先a=A(),实例化了这个类,而init这个初始化的意思在于,传递参数给self这个实例对象,类似于java中的this,是一个实例,现在a这个对象中,有name和age属性,因为在初始化实例的时候并咩有赋值,所以参见默认的值,所以第一个print的时候打出的是实例a的name和age属性,第二个属性进行属性的二次修改,如果你不想用init中的默认属性而忘记在实例化的时候进行参数传递,那么,再构建方法的时候再把这个实例的属性进行修改就可以了! 第三个print调用了实例的Me1方法,可以在这一层传递参数进去。第二个b实例化的时候就传递了参数进去,这会作用在init这个初始化中

研究一下输出就可以把init和默认值,self搞的清楚了,这么个意思,教科书有点啰嗦


一个比较好的例子


class person():
    def __init__(self,name,gender,birth,**kw):
        self.name=name
        self.gender=gender
        self.birth=birth
        for k,w in kw.iteritems():
            setattr(self,k,w)
    def sayhi(self):
        print 'my name is',self.name
xiaoming = person('Xiao Ming', 'Male', '1991-1-1',job='student',tel='18089355',stdid='15010')
xiaohong = person('Xiao Hong', 'Female', '1992-2-2')
print xiaoming.name
print xiaohong.birth
print xiaoming.job
print xiaoming.tel
print xiaoming.stdid
print xiaoming.sayhi()  # 输出两个值,一个是print的内容,另一个是None

Xiao Ming
1992-2-2
student
18089355
15010
<__main__.person instance at 0x10c7dc290>
__main__.person
my name is Xiao Ming
None

进阶版,包含继承和super,默认值

__metaclass__ = type  # 想用super就先加上
class A:

    def __init__(self,name='from init',age=0):
        self.name =name
        self.age =age

    def Me1(self,name_Me1='from Me1',age_Me1=1):
        print self.name,self.age
        print name_Me1,age_Me1

class B(A):

    def __init__(self,name_b='默认的name_b',age_b=5):
        super(B, self).__init__(name='在B类初始化时已修改',age=4)
        self.name_b = name_b
        self.age_b = age_b

    def Me2(self,name_Me2='默认的name_Me2',age_Me2=7):
        print self.name,self.age
        print self.name_b,self.age_b
        print name_Me2,age_Me2



print '---------------'
b = B('修改默认值',6)
print '---------------'
b.Me1()
print '---------------'
b.Me1('修改Me1',2)
print '---------------'
b.Me2()
print '---------------'
b.Me2('修改Me2',8)
print '---------------'
a = A('修改A中init',10)
a.Me1()

可以自己试一下,应该输出什么呢?

---------------
---------------
在B类初始化时已修改 4
from Me1 1
---------------
在B类初始化时已修改 4
修改Me1 2
---------------
在B类初始化时已修改 4
修改默认值 6
默认的name_Me2 7
---------------
在B类初始化时已修改 4
修改默认值 6
修改Me2 8
---------------
修改A中init 10
from Me1 1

这里挑其中的一个解释一下;
就解释b.Me1()这个吧,刚开始b被带参数的实例化,然后调用Me1方法,这个方法是在A类中的,因为B继承于A类,所以A中的方法b都可以调用,别急着往A类上找Me1方法,实例化B的过程中,先进行的是init这个构造方法,也就是初始化,那么初始化的过程中,用了super的超继承,也就说,B的init函数中,原封不动的把A的init搬过来,而且,在super中传入了默认参数,然后B的init又加了自己的self。当超类使用时候,因为在b.Me1()这个并没有传入参数,所以name_Me1这个属性值默认,不做修改,妈呀,总算解释完了,有点绕是吧,这得自己推一下。。。。。


今天就先写到这—老纸要写开题报告了窝草。

这里写图片描述


python 3.6 中补充下
因为新式类和经典类的原因,在python2.x中的多继承是深度优先遍历(经典类);而在python3.x中多继承只保留了新式类,而类继承关系则按照 C3遍历(并非广度优先);至于super()中的参数传递,可以参考:Python3中super()的参数传递


class Base(object):
    def __init__(self):
        print('Base.__init__')


class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')
    def call(self):
        print("call A")
        super().call()
        


class B(Base):
    def __init__(self):
        super().__init__()
        print('B.__init__')
    
    def call(self):
        print("call B")
    


class C(Base):
    def __init__(self):
        super().__init__()
        print('C.__init__')
    
    def call(self):
        print("call C")
        super().call()
        
        


class D(A, C, B):
    def __init__(self):
        super().__init__()  # 等同于 super(D, self).__init__(), 从D开始根据mro往后找,一层层往上找的的时候遵循类似“递归”的链式
        print('D.__init__')
    
    def call(self):
        print("call D")
        super(A, self).call() # 从C(不包含C)开始根据mro往后找
       
        

d = D()
d.call()

print(D.mro())


# 结果

Base.__init__
B.__init__
C.__init__
A.__init__
D.__init__
call D
call C
call B
[<class '__main__.D'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

上述可以看到,当使用super(A, self).call()的方式时,根据mro的继承顺序,从A之后的也就是B开始调用执行,而不带参数的super()默认都是从自身的类向后开始执行,如super().__init__()可以等效为super(D, self).__init__(),也就是按照顺序开始执行A-C-B-BASE

一般的:super(type, obj)的参数为一个类和一个对象的时候,得到的是一个绑定的super对象。但是obj必须是type的实例或者是子类的实例。

你可能感兴趣的:(Python基础)