Python进阶:元类

元类

一.类也是对象

在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段,在python中这点任然成立,但是远不止与此,在python中,类同样也是对象,只要你使用关键字class,Python解释器在执行的时候就会创建一个对象。

class ObjectCreator(object):
               pass

这段代码会在内存中创建一个对象,名字就是ObjectCreator。这个对象(类对象ObjectCreator)拥有创建对象(实例对象)的能力。但是,它的本质仍然是一个对象,于是乎你可以对它做如下的操作:

  1. 你可以将它赋值给一个变量
  2. 你可以拷贝它
  3. 你可以为它增加属性
  4. 你可以将它作为函数参数进行传递

二.动态的创建类

1).因为类也是对象,你可以在运行时动态的创建它们,就像其他任何对象一样。首先,你可以在函数中创建类,使用class关键字即可。

 
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())#可以通过这个类创建类实例,即对象

2).使用type创建类

type可以查看对象的类型,当使用type对ObjectCreator查看类型是type

type还有一种完全不同的功能,动态的创建类。

格式:type(类名,由父类名称“不是字符串”组成的元组(可以为空),包含属性的字典(名称和值))

dwx=type("dwx",(),{"age":10})#创建类dwx
a=dwx()
print(a.age)
  • type的第2个参数,元组中是父类的名字,而不是字符串
  • 添加的属性是类属性,并不是实例属性

 使用type创建带有方法的类

def sum(self,a,b):
    return a+b
test=type("test",(),{"sum":sum})
a=test()
print(a.sum(1,2))

类方法与静态方法都一样

在Python中,类也是对象,你可以动态的创建类。这就是当你使用关键字class时Python在幕后做的事情,而这就是通过元类来实现的。

三.元类

元类就是用来创建类的东西

函数type实际上是一个元类。type就是Python在背后用来创建所有类的元类。

元类就是创建类这种对象的东西。type就是Python的内建元类

四.__metaclass__属性

可以在定义一个类的时候为其添加__metaclass__属性。

class Foo(object):
    __metaclass__=something
    

首先写下class Foo(object),但是类Foo还没有在内存中创建。Python会在类的定义中寻找__metaclass__属性,如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用内建的type来创建这个类。

当写下如下代码时:

class Foo(Bar):
    pass

Python做了如下的操作:

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

现在的问题就是,你可以在__metaclass__中放置些什么代码呢?答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东东都可以。

五.自定义元类

就元类本身而言,它们其实是很简单的:

  1. 拦截类的创建
  2. 修改类
  3. 返回修改之后的类
    class UpperAttrMetaClass(type):
        # __new__ 是在__init__之前被调用的特殊方法
        # __new__是用来创建对象并返回之的方法
        # 而__init__只是用来将传入的参数初始化给对象
        # 你很少用到__new__,除非你希望能够控制对象的创建
        # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
        # 如果你希望的话,你也可以在__init__中做些事情
        # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
        def __new__(cls, future_class_name, future_class_parents, future_class_attr):
            #遍历属性字典,把不是__开头的属性名字变为大写
            newAttr = {}
            for name,value in future_class_attr.items():
                if not name.startswith("__"):
                    newAttr[name.upper()] = value
    
            # 方法1:通过'type'来做类对象的创建
            # return type(future_class_name, future_class_parents, newAttr)
    
            # 方法2:复用type.__new__方法
            # 这就是基本的OOP编程,没什么魔法
            # return type.__new__(cls, future_class_name, future_class_parents, newAttr)
    
            # 方法3:使用super方法
            return super(UpperAttrMetaClass, cls).__new__(cls, future_class_name, future_class_parents, newAttr)

    class Foo(object, metaclass = UpperAttrMetaClass):

猜你喜欢

转载自www.cnblogs.com/python-road/p/10494353.html