Python中的元类

来源:互联网 发布:修改sql触发器 编辑:程序博客网 时间:2024/05/16 14:41

万物皆对象,在Python也是这样,类也是对象,但是Python不像Java这样有反射,Python有元类,元类就是创建类的类。

既然类也是对象,所以你可以对类进行如下操作。

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

  2.你可以拷贝它

  3.你可以为它增加属性

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

  5.可以像创建对象一样,动态的创建类

1.type的使用。说明:当只有一个参数的时候,代表判断参数的类型,type(type)依然是type,即元类是类的类,type是类最根本的元类

In [1]: a=1In [2]: type(a)Out[2]: intIn [3]: type(int)Out[3]: typeIn [4]: a=[]In [5]: type(a)Out[5]: listIn [6]: type(list)Out[6]: typeIn [7]: def func():   ...:     pass   ...: In [8]: type(func)Out[8]: functionIn [9]: type(type(func))Out[9]: typeIn [10]: type(type)Out[10]: type

2.type(三个参数)。说明,当type()有三个参数时,表示手动的创建类,

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

 

# 添加类属性a = 100# 添加对象属性def __init__(self):    self.obj_a = 100# 添加对象方法def obj_fun(self):    print("obj_fun")# 添加类方法@classmethoddef cls_fun(cls):    print("cls_fun", cls.a)# 添加静态方法@staticmethoddef sta_fun():    print("static_fun")Foo1 = type("Foo", (object,),            {"a": a, "obj_fun": obj_fun, "cls_fun": cls_fun, "sta_fun": sta_fun, "__init__": __init__})print(Foo1.__name__)print(Foo1.a)Foo1.cls_fun()Foo1.sta_fun()f = Foo1()f.obj_fun()print(f.obj_a)

 # Foo
 # 100
 # cls_fun 100
 # static_fun
 # obj_fun
 # 100

3.使用函数的方式创建元类。说明:可以控制创建类的过程,但是最终还是需要依赖于type。

def upper_meta_class(class_name, class_bases, class_attrs):    new_class_attrs = {}    for key, value in class_attrs.items():        new_class_attrs[key.upper()] = value    return type(class_name, class_bases, new_class_attrs)class Foo(object, metaclass=upper_meta_class):    a = 100    b = 100# FOO = upper_meta_class("Foo", (object,), {"a": 1, "b": 2})  # 这种方式可以重新定义返回的类名,所以参数和最终的类名没有关系# print(FOO.A)  # 100print(Foo.A)  # 通过metaclass处理的类,无法更改类名

 

4.使用类的方式创建元类。说明:你可以在定义一个类的时候为其添加__metaclass__属性。如果找到了,Python就会用它来创建类Foo,如果没有找到,就会用      内建的type来创建这个类。

   Python做了如下的操作:

  1. Foo中有__metaclass__这个属性吗?如果是,Python会通过__metaclass__创建一个名字为Foo的类(对象)
  2. 如果Python没有找到__metaclass__,它会继续在Bar(父类)中寻找__metaclass__属性,并尝试做和前面同样的操作。
  3. 如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。
  4. 如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。
class UpperMetaClass(type):    def __new__(cls, class_name, class_bases, class_attrs):        new_class_attrs = {}        for key, value in class_attrs.items():            new_class_attrs[key.upper()] = value        # return type(class_name, class_bases, new_class_attrs) # 第一种        # return type.__new__(cls, class_name, class_bases, new_class_attrs)  # 第二种        # return super().__new__(cls, class_name, class_bases, new_class_attrs)  # 第三种 ,super()不带参数只支持python3        return super(UpperMetaClass, cls).__new__(cls, class_name, class_bases, new_class_attrs)  # 第四种,带参数支持py2和py3# 使用python3创建元类的方法class Foo(object, metaclass=UpperMetaClass):    a = 100    b = 100# # 使用python2创建元类的方法# class Foo(object):#     __metaclass__ = UpperMetaClass#     a = 100#     b = 100print(Foo.A)  #

总结:

元类就是用来创建这些类(对象)的,元类就是类的类,Python中所有的东西,注意,我是指所有的东西——都是对象。

这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来,这个类就是type。

自定义类的创建过程:拦截类的创建,修改类,返回修改之后的类。

Python中元类很少用,引用一句经典的话:
“元类就是深度的魔法,99%的用户应该根本不必为此操心。如果你想搞清楚究竟是否需要用到元类,那么你就不需要它。那些实际用到
元类的人都非常清楚地知道他们需要做什么,而且根本不需要解释为什么要用元类。” —— Python界的领袖 Tim Peters

 
原创粉丝点击