Python 类 - zhongjiajie/zhongjiajie.github.com GitHub Wiki
# 默认, Python 3
class A:
pass
# Python 2
class A(object):
pass
通过super
可以调用父类的方法,避免了重复代码,方便维护,是类继承设计的其中一个目的.super的简单使用
class MySuper(object):
def __init__(self,a):
self.a = a
class MySub(MySuper):
def __init__(self,a,b):
self.b = b
super().__init__(a)
my_sub = MySub(42,'chickenman')
print(my_sub.a) # 42
print(my_sub.b) # chickenman
# a变量的赋值没有放在子类中,而是放在父类中完成
py2和py3中的区别: python3中super() -> same as super(__class__, self)
, python2中则要使用super(CurrentClass, self)
所以python3中可以这样使用here
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
如果运行
b = B()
b.add(2)
print(b.n)
得到的结果如下:
self is <__main__.B object at 0x106c49b38> @B.add
self is <__main__.B object at 0x106c49b38> @A.add
8
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m)
self.n += 4
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
print('self is {0} @D.add'.format(self))
super().add(m)
self.n += 5
运行
d = D()
d.add(2)
print(d.n)
输出结果如下
self is <__main__.D object at 0x10ce10e48> @D.add
self is <__main__.D object at 0x10ce10e48> @B.add
self is <__main__.D object at 0x10ce10e48> @C.add
self is <__main__.D object at 0x10ce10e48> @A.add
19
因为此时的MRO(Method Resolution Order)
列表为[D, B, C, A, object]
通常我们将有实际意义的属性通过函数的方式暴露给用户使用,而不是直接将对象本身传递给用户,这样做可以对参数进行检验,也使得参数更加安全不能被任意的使用者调用,如果使用函数,则对应的get/set方法就会变成Obj.set_attr(value)/Obj.set_attr()
.这样对调用者比较不友好,他们更希望的get/set方法是obj.attr=value/obj.attr
(和直接调用属性的方式一样)
class Student(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
把一个getter方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作
>>> s = Student()
>>> s.score = 60 # OK,实际转化为s.set_score(60)
>>> s.score # OK,实际转化为s.get_score()
60
>>> s.score = 9999
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
还可以通过@property
设置只读属性,如下,birth
是可读可写的对象,age
是只读对象
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2014 - self._birth
不要在类中__init__
中使用可变对象作为默认值,如果要使用默认值,应该在__init__
中默认值设为None
,且在函数体中实现可变对象的赋值
class tmp:
def __init__(self, a, b=None):
self.a = a
self.b = b or [] # b or []或选取第一个不为None的值
-
__new__
: 返回一个新的类的实例 -
__init__
: 对类实例进行初始化