python 中的元类详解

在其他语言中我们都知道类和int,string等类型一样是用来生成对象的。
类就是生成对象的代码段。
在python中任然是这样,但是Python中的类还远不止如此,在python中类也是对象。只是这个对象拥有创建对象的能力。

但是,它的本质仍然是一个对象,于是乎你可以对它做如下的操作:

  1. 你可以将它赋值给一个变量

  2. 你可以拷贝它

  3. 你可以为它增加属性

  4. 你可以将它作为函数参数进行传递

同时因为类就是对象,所以可以在运行时动态的创建。

def choose_class(name):
…       if name == 'foo':
…           class Foo(object):
…               pass
…           return Foo     # 返回的是类,不是类的实例
…       else:
…           class Bar(object):
…               pass
…           return Bar
…
>>> MyClass = choose_class('foo')
>>> print MyClass              # 函数返回的是类,不是类的实例

>>> print MyClass()            # 你可以通过这个类创建类实例,也就是对象
<__main__.Foo object at 0x89c6d4c>

由于类也是对象,所以它们必须是通过什么东西来生成的才对。当你使用class关键字时,Python解释器自动创建这个对象。

使用type来创建类

我们都知道python中的自身,使用type可以知道当前变量的类型

print type(1)

print type("1")

type可以这样使用

type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

比如用type来创建下面的一个类

class Foo(object):
    bar = True

使用type简化创建

Foo = type('Foo', (), {'bar':True})

使用继承,
在创建一个下面的子类

class FooChild(Foo):
…       pass
FooChild = type('FooChild', (Foo,),{})
print FooChild

print FooChild.bar   # bar属性是由Foo继承而来
True

使用type为你的类增加方法


def echo_bar(self):
        print self.bar

FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
hasattr(Foo, 'echo_bar')
False
hasattr(FooChild, 'echo_bar')
True
my_foo = FooChild()
my_foo.echo_bar()
True

已定义的元类

==type==就是Python在背后用来创建所有类的元类。除此外还有==str==,==int==等内件元类

创建自己的元类

你可以在写一个类的时候为其添加metaclass属性。

class Foo(object):
    __metaclass__ = something…

Foo中有metaclass这个属性吗?如果是,Python会在内存中通过metaclass创建一个名字为Foo的类对象。如果Python没有找到metaclass,它会继续在Bar(父类)中寻找metaclass属性,并尝试做和前面同样的操作。如果Python在任何父类中都找不到metaclass,它就会在模块层次中去寻找metaclass,并尝试做同样的操作。如果还是找不到metaclass,Python就会用内置的type来创建这个类对象。

比如将属性全部转化为大写

# 元类会自动将你通常传给‘type’的参数作为自己的参数传入
def upper_attr(future_class_name, future_class_parents, future_class_attr):
    '''返回一个类对象,将属性都转为大写形式'''
    #  选择所有不以'__'开头的属性
    attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
    # 将它们转为大写形式
    uppercase_attr = dict((name.upper(), value) for name, value in attrs)
 
    # 通过'type'来做类对象的创建
    return type(future_class_name, future_class_parents, uppercase_attr)
 
__metaclass__ = upper_attr  #  这会作用到这个模块中的所有类
 
class Foo(object):
    # 我们也可以只在这里定义__metaclass__,这样就只会作用于这个类中
    bar = 'bip'

Python中的一切都是对象,它们要么是类的实例,要么是元类的实例,除了type。type实际上是它自己的元类。

你可能感兴趣的:(python 中的元类详解)