改善python程序-元类编程

掌握metaclass

  • 元类是关于类的类,是类的模板
  • 元类是用来控制如何创建类的,正如类是创建对象的模板一样
  • 元类的实例为类,正如类的实例为对象
    类是对象,那么它就有其所属的类型为type
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # type(类名,父类的元绍(针对继承的情况,可以为空),包含属性的字典(名称和值))
    >>> A=type('A', (object,), {'value':2})
    >>> A.value
    >>> print A
    <class '_main_.A'>
    >>> class C(A):
    ... pass
    >>> print C
    <class '_main_.C'>
    >>> print C.__class__
    <type 'type'>

自定义元类(强制类型检査)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Typesetter(object):
def__init__(self,fieldtype):
print "set attribute type",fieldtype
self .fieldtype = fieldtype
def is_valid(self,value):
return isinstance(value, self.fieldtype)
class TypeCheckMeta(type):
def __new__(els, name, bases, diet):
print '-------------------'
print "Allocating memory for class", name
print name
print bases
print diet
return super(TypeCheckMeta, els).__new__(els,name,bases,diet)
def __init__(els,name,bases,diet):
els._fields = {}
for key,value in diet.items():
if isinstance(value,Typesetter):
els._fields[key] = value
def sayHi(els):
print "Hi"
class TypeCheck(object):
__metaclass__ = TypeCheckMeta
def __setattr__(self,key,value):
print "set attribute value"
if key in self._fields:
if not self._fields[key].is_valid (value):
raise TypeError (' Invalid type for field')
super(TypeCheck,self).__setattr__(key,value)
class MetaTest(TypeCheck):
name = TypeSetter(str)
num = TypeSetter(int)
mt = MetaTest()
mt.name = "apple"
mt.num = "test"

在新式类中当一个类未设置metaclass属性的时候,它将使用默认的type元类来生成类。而当该属性被设罝时査找规则如下: 如果存在dict[‘metaclass‘],则使用对应的值来构建类;否则使用其父类dict[‘metaclass‘]中所指定的元类来构建类,当父类中也不存在指定的metaclass的情形下使用默认元类type;条件1不满足的情况下,如果存在全局变量metaclass,则使用该变量所对应的元类来构建类;否则使用types.ClassType。

元类的场景

(1)元类来实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
class Singleton(type):
def __init__(cls,rname,bases,dic):
super(Singleton,els).__init__(name,bases,dic)
cls.instance = None
def __call__(els,*args,**kwargs):
if els.instance is None:
print "creating a new instance'
els.instance = super(Singleton,els).__call__(*args,**kwargs)
else:
print "warning:only allowed to create one instance,minstance already exists!"
return els.instance
class MySingleton(object):
__metaclass__ = Singleton

(2)区别类方法与元方法:元方法可以从元类或者类中调用,而不能从类的实例中调用;但类方法可以从类中调用,也可以从类的实例中调用.
(3)多继承需要严格限制