介绍装饰器、继承、元类、mixin,四种給类动态添加类属性和方法的方式
有时候需要給类添加额外的东西,有些东西很频繁,每个类都需要,如果不想反复的复制粘贴到每个类,可以动态添加。
1 #coding=utf-8
2
3 defcreate_class_attribution(cls):4 def _inner(*args, **kwargs):5 if not hasattr(cls, 'xx'):6 cls.xx = 1
7
8 deffuna(self, a, b):9 return a +b10
11 if not hasattr(cls, 'funa'):12 cls.funa =funa13 return cls(*args, **kwargs)14
15 return_inner16
17
18 classBase():19 #__metaclass__ = Meta
20 def __new__(cls, *args, **kwargs):21 if not hasattr(cls, 'yy'):22 cls.yy = 2
23 return super().__new__(cls)24
25 deffunb(self, a, b):26 return a +b27
28
29 classMyType(type):30 def __new__(cls, name, bases, attrs):31 attrs['zz'] = 3
32 attrs['func'] = lambda self, a, b: a +b33 return super(MyType, cls).__new__(cls, name, bases, attrs)34
35
36 classMyMixin():37 def __init__(self, *args, **kwargs):38 if not hasattr(self, 'ww'):39 self.__class__.ww = 4
40
41 deffund(self, a, b):42 return a +b43
44
45 @create_class_attribution46 class A(MyMixin, Base, metaclass=MyType):47 pass
48
49
50 a =A()51 print(a.xx)52 print(a.yy)53 print(a.zz)54 print(a.ww)55 print (a.funa(1, 2))56 print (a.funb(3, 4))57 print (a.func(5, 6))58 print (a.fund(7, 8))
这样就完成了给类添加属性和方法了。
A类什么都不写,a的实例就有4个自定义的方法和4个属性了。
1、其中,元类,是在代码不进行任何对类的调用,就已经运行了。可以打印下就知道了。这和其他几个惰性的添加属性和方法不同 。相关的可以看下菜鸟教程的java单例模式中的饿汉和饱汉,我喜欢用饱汉模式,程序启动速度快,特别是有人喜欢把io操作的结果赋值给类属性还仍然使用饿汉模式,会大幅降低程序启动速度。
关于元类的理解,就是创建类的类,默认是有type类来创建所有类。用的时候把普通类想象成实例,元类想象成类,这样就能脑袋转过弯使用他了。
所以元类可以影响类的__dict__,但影响不了实例的__dict__。
2、装饰器版本,没啥好说的了,给类添加属性
3、继承版本,很普通的,和mixin版本代码都一模一样。继承是is的关系,mixin是can的关系,mixin充当的功能应该类似于java的接口,但带了方法实现。
比如动物类,有猪、燕子、麻雀,这三个都可以继承动物类,燕子和麻雀除了可以继承动物类,还可以继承一个有飞行方法的mixin类。猪就不要继承这个mixin了。燕子是动物,燕子能够飞行,但燕子不是飞行。is can或者has的概念。
除这四种方式外,还有组合的方式加属性,见(二)