python 中的元类详解

作者: Tim在路上 | 来源:发表于2018-10-03 20:30 被阅读0次

    在其他语言中我们都知道类和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              # 函数返回的是类,不是类的实例
    <class '__main__'.Foo>
    >>> print MyClass()            # 你可以通过这个类创建类实例,也就是对象
    <__main__.Foo object at 0x89c6d4c>
    

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

    使用type来创建类

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

    print type(1)
    <type 'int'>
    print type("1")
    <type 'str'>
    

    type可以这样使用

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

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

    class Foo(object):
        bar = True
    

    使用type简化创建

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

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

    class FooChild(Foo):
    …       pass
    
    FooChild = type('FooChild', (Foo,),{})
    print FooChild
    <class '__main__.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 中的元类详解

        本文链接:https://www.haomeiwen.com/subject/kzazoftx.html