继承
instance.class #查看实例所属的类
在子类中可以重写父类的方法(名称相同),那么在子类里,父类原来的方法被覆盖就无效了。
如果在子类中重写__init__(self),想要继承父类的___init__怎么办? 两种方法:
- father_class.
__init__
(self,属性)
class son_class(father_class):
def __init__(self,teacher,web):#web为父类参数
self.teacher = teacher
father_class.__init__(self,web) #unbound menthod!
- super函数
class son_class(father_class):
def __init__(self,teacher,web):#web为父类参数
self.teacher = teacher
super(son_class,self).__init__(web)
#查看继承顺序
类名.__mro__
#查看类的属
类名.__dict__
继承顺序是广度优先,即先搜索上一层的所有父类,然后再从头开始搜索父类的父类,DBS。
方法
绑定方法与非绑定方法
class foo():
def bar(self):
print('normal class')
>>> f = foo()
>>> f.bar()
normal class
>>> foo.bar()
Traceback (most recent call last):
File "", line 1, in
foo.bar()
TypeError: bar() missing 1 required positional argument: 'self'
>>> foo.bar(f)
normal class
foo.bar()是一个非绑定方法;f.bar()是一个绑定方法;
实例
>>> foo.bar
>>> f.bar
>
>>>
>>> foo.__dict__
mappingproxy({'__dict__': , '__weakref__': , '__doc__': None, 'bar': , '__module__': '__main__'})
>>> foo.__dict__['bar']
>>> foo.__dict__['bar']()
Traceback (most recent call last):
File "", line 1, in
foo.__dict__['bar']()
TypeError: bar() missing 1 required positional argument: 'self'
>>> foo.__dict__['bar'](f)
normal class
>>> foo.__dict__['bar'].__get__(None,foo)
>>> foo.__dict__['bar'].__get__(f,foo)
>
小结一下:
- ’dict’方法返回类的所有属性和方法,并且是个字典,可以调用
- ‘get’方法能够调用类方法,在参数为None时(类本身)为非绑定方法,参数为实例时,为绑定方法
- 总之,类调用方法,就是非绑定方法(注意要加进去实例参数);实例调用方法,就是绑定方法(实例隐式传入)。
类方法与静态方法
类方法
class foo(object):
one = 0
def __init__(self):
foo.one = foo.one + 1
@classmethod
def bar(cls):
return cls.one
if __name__ == '__main__':
f1 = foo()
print(foo.one)
f2 = foo()
print(foo.one)
print(f1.bar())
print(f1.one)
print(foo.bar())
print('*'*10)
f1.one = 8
foo.one = 9
print(f1.one)
print(f1.bar())
print(foo.bar())
>>>
1
2
2
2
2
**********
8
9
9
>>>
我们发现无论是用实例还是类来调用加了装饰器@classmethod的函数bar(),都是返回类的属性;而且我们发现类属性可以和实例的类属性不同(这是什么鬼啊)。类方法的目的在于把类传进来而不用把函数写在外面。
静态方法
@staticmethond这种方法跟在类外定义一个普通函数相同(只是把类外函数写进来了而已),但是在调用的时候要用self.func()来调用。
t = 0
class foo():
def __init__(self,name):
self.name = name
@staticmethod
def bar():
t = 99
return t
def get_name(self):
if self.bar():
return self.name
else:
return 'no person'
if __name__ == "__main__":
f = foo('cangjingkong')
name = f.get_name()
print(name)
>>>
cangjingkong
>>>
其实很无聊感觉。
两种方法的比较与总结
其实,感觉都差不多@classmethod是为了把类外使用类作为参数的函数写进来,参数为cls(类,但是你可以随意命名)而且无论是绑定方法还是非绑定方法调用(可耻地用了术语),都返回的是类属性,而不是实例的类的属性(好拗口);@staticmethod是为了把类外的函数写进来,参数像在类外写函数一样,没有self,但是在类内调用的时候要用self。
以上。