Python中的元类

本文深入探讨了Python中的元类概念,介绍了如何使用type函数创建类,以及如何通过自定义元类来控制类的创建过程。文章还展示了元类的具体应用案例。

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

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

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

  2.你可以拷贝它

  3.你可以为它增加属性

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

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

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

In [1]: a=1

In [2]: type(a)
Out[2]: int

In [3]: type(int)
Out[3]: type

In [4]: a=[]

In [5]: type(a)
Out[5]: list

In [6]: type(list)
Out[6]: type

In [7]: def func():
   ...:     pass
   ...: 

In [8]: type(func)
Out[8]: function

In [9]: type(type(func))
Out[9]: type

In [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")


# 添加类方法
@classmethod
def cls_fun(cls):
    print("cls_fun", cls.a)


# 添加静态方法
@staticmethod
def 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)  # 100

print(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 = 100


print(Foo.A)  #

总结:

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

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

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

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

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值