1. 类即为对象
类同样也是一种对象. 只要你使用关键字class, Python解释器在执行的时候就会创建一个对象. 下面的代码段:
C既是一个类, 它可以创建对象;同时C也是一个对象, 可以当做参数进行传递, 也可以被赋值, 被拷贝.
2. 动态地创建类
由于类也是对象, 所以可以在运行时动态创建类, 就像任何时刻都可以创建对象一样.
def choose_class(name): if name == '1': class C1(object): pass return C1 else: class C2(object): pass return C2
C = choose_class('1') print C()
|
上述例子中依然需要提前写好自己需要的类代码, 为了实现动态的生成类代码, 我们需要用到内建函数type()
3. type()函数
type()
函数最基本的功能就是让你知道个对象的类型, 例如:
print type(1) print type("123") print type(type(1))
class C(object): pass
print type(C) print type(C())
|
但type()
还有一种完全不同的应用: 动态地创建类. type()
可接受一个类的描述并返回一个类: type(类名, 父类的元组, 包含属性或函数的字典)
. 例如:
class C1(object): pass
C2 = type('C2', (), {})
print C1 print C2
|
也可以定义类属性:
class C1(object): a = 1
C2 = type('C2', (), {'a': 2})
c1 = C1 c2 = C2
print c1.a print c2.a
|
还可以使用type()
定义类函数:
class C1(object): def func(self): print self.name def __init__(self, name): self.name = name
def func(self): print self.name
def __init__(self, name): self.name = name
C2 = type('C2', (), {'__init__': __init__, 'func': func})
c1 = C1('1') c2 = C2('2')
c1.func() c2.func()
|
4. 元类概念
类是对象, 但类对象由谁实例化的呢? metaclass(元类)负责实例化每一个类, 也就是类的类:
Class = MetaClass() Intance = Class()
|
上一节我们介绍了使用type()
动态地创建类, 其实type就是一个元类. 由此推出, str
是所有字符串对象的类, int是所有整数的类, 它们的元类都是Python的内建元类type:
print type(1) print type("123") print type(str) print type(int)
|
也可以使用__class
__`查看自己属于哪个类:
a1 = 1 a2 = '1' print a1.__class__ print a2.__class__ print int.__class__ print str.__class__
|
5. 如何使用元类
由于type是元类, 所以可以用来创建子类:
class ChildType(type): def __new__(cls, name, bases, dct): print "Allocate memory for class", name return type.__new__(cls, name, bases, dct)
def __init__(cls, name, bases, dct): print "Init class ", name super(ChildType, cls).__init__(name, bases, dct)
X = ChildType('X', (), {'foo': lambda self: 'foo'})
print X, X().foo()
|
也可以将类方法放在生成的类上:
class Printable(type): def whoami(cls): print "I am a", cls.__name__
Foo = Printable('Foo', (), {}) Foo.whoami()
Printable.whoami()
|
还可以通过设置__metaclass__
类属性来定制元类创建类, 但必须在类定义时设置__metaclass__
属性, 如果在创建类对象之后再设置该属性, 就不会使用元类:
class ChildType(type): def typemethod(cls): return cls.__name__
class C: __metaclass__ = ChildType
def classmethod(self): return 'class'
print C.typemethod() print C().classmethod()
|
6. 元类解决的问题
通常会使用元类去做一些晦涩的事情. 就元类本身而言, 其实是很简单的:
- 拦截类的创建
- 修改类
- 返回修改之后的类
需要注意以下几点:
- 元类中,
type
的调用才会真正创建类, 所以可以自由地改变属性字典(以及名称和元组形式的基类序列).
- 一些Python ORM(Object Relational Mappers, 对象关系影射)实现了面向对象编程语言里不同类型系统的数据之间的转换.
- 由于元类是继承的, 所以你能够提供一个使用了你的元类的基类, 而继承自它的子类就无需显式声明它了.
下面是一个例子:
class UpperAttrMetaclass(type): def __new__(cls, name, bases, dct): attrs = ((name, value) for name, value in dct.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return super(UpperAttrMetaclass, cls).__new__(cls, name, bases, uppercase_attr)
class Foo(object): __metaclass__ = UpperAttrMetaclass bar = 'bip'
f = Foo() print f.BAR
print f.bar
|