作为高级面向对象语言,Python 非常的灵活。
__slots__
定义一个学生对象,
1 | class Student(object): |
一般语言,都是在初始化对象的时候,先定义好对象的属性和方法。
而 Python 可以在程序运行的过程中,动态的添加属性和方法。
实例动态添加属性:
1 | class Student(object): |
非常 easy 。
实例动态添加方法:
1 | class Student(object): |
注意两点: MethodType()
方法传入两个参数,第一个是方法,第二个是对象,还有实例动态添加属性,加的只是该实例的属性,不是对象的属性。
对象动态添加方法:
1 | class Student(object): |
对象添加的属性,所有实例都可以使用。
Java 使用者表示,这也太灵活了吧,难道都随便添加属性和方法吗? 不,用 __slots__
这个特殊的变量就具有限制的作用。
slot 这个单词有硬币投币口的意思。
用法:
1 | class Student(object): |
很明显,没有出现在 slots 白名单的属性是不允许被添加的:
1 | Traceback (most recent call last): |
注意一点:这个白名单默认是不被继承的,当子类也定义白名单的时候,父类白名单才会被激活。
@property
正常情况下我们的 get()
set()
是这样写的:
1 | #!/usr/bin/env python |
运行结果当然是: 50 。
但是调用的过程对于 Python 来说不够优雅,于是有了神奇的 @property 。
它的用处就是将调用 set()
和 get()
方法的形式变成直接使用属性的方式改变对应的 value
。
1 | #!/usr/bin/env python |
这里特别特别要注意的是,age
值前面加了 _
。
如果想要该属性变成只能读,而不能写,那么不要写 setter
方法就行了。
1 | #!/usr/bin/env python |
如果加了 stu.age = 50
就会报错:
1 | AttributeError: can't set attribute |
__str__
用于打印属性:
1 | class Student(object): |
结果为:
1 | Student object (name: zlf) |
__iter__
和 __getitem__
前者将类作用于循环:
1 | for n in Fib(): |
后者让类的循环可以直接使用下标:
1 | f = Fib() |
栗子:
1 | #!/usr/bin/env python |
结果:
1 | 8 |
__call__
让对象的实例可以直接调用:
1 | class People(object): |
结果:
People can talk .
这么看来函数和对象还是很像的。
__getattr__
调用不存在的属性时使用 __getattr__()
方法可以动态返回一个属性:
1 | class Student(object): |
结果是 99
当定义属性存在时,再定义 __getattr__
是无效的:
1 | class Student(object): |
结果是 12
多继承
Python 支持多继承。那么第一个想到的问题一定是,如果两个父类中拥有相同的方法,子类怎么办?
看一段网友提供的代码就清楚了:
1 | #!/usr/bin/env python |
运行的结果是:
1 | A |
很容易理解,哪个在父类在前面,就用哪个父类中的方法。
当我一番搜索关于 Mixin
的概念之后,我觉得, Python 其实不算真正意义上的多继承,而更像是单继承多实现。
继承强调的是 I am , Mixin
强调的是 I can 。
Mixin
的使用是为了获得多继承的优点,或者说就是一种语法糖:在编译的时候将一段代码复制到了另一个地方。同时它也避免了多重继承的时候出现的类与类之间的关系过于混乱的问题。
它的使用就是在后面的父类中加个后缀:
1 | class Dog(Mammal, RunnableMixin, CarnivorousMixin): |
Carnivorous 是食肉的意思,Mixin 是混入的意思
参考链接:
缪雪峰官网
Mixin 是什么概念
Python Mixin 模式
Python 多继承
未完待续…