Python 2.7
IDE Pycharm 5.0.3
遇到问题,解决问题,才能不愧对自己花费的时间--小白语录
建议首先阅读:
@追梦的蜗牛果果–Python 继承之 self的解释
@LY_ysys629–python类class中_init_函数以及参数self的简单解释
类的属性:类中所涉及的变量
类的方法:类中函数
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
的实例或者是子类的实例。