python中的元类

我们都知道,当创建一个类后,可以通过它创建对象

1、对象可以在程序中动态的进行创建

2、对象可以通过__class__获取该对象所属的类

3、对象可以动态的添加属性

4、可以使用type查看对象的类型

通过实验,发现类同样可以实现上述四步,也就是说类其实也是由类创建出来的。这个用来创建类的类就叫元类

通过__class__属性得到类的类型都是byte所以byte就是元类

一.type用法

1、查看当前对象的类型

2、创建类

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

原理:type()返回一个类对象(如下边的B,Person),类对象可以再生成对象(b,a,person)

class A(object):# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<正常创建类
    def __init__(self):
        print('A')

#  语法:type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
B = type('B', (), {'name': '鬼子'})#  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<type创建类
b = B()
a = A()
print(b.name)
print(type(A))
print(type(B))

结果:

类A
鬼子
<class 'type'>
<class 'type'>

那么怎么让元类包含方法呢?lambda来啦!!!!!!

Person = type('Person', (), {'name': '鬼子', 'say': lambda a: print(a.name)})
person = Person()
person.say()

结果:

鬼子

让我们再深入认识类以及元类

当我们创建一个类如:

class XX( ):

    pass

到底执行了什么?

在该类定义的时候,它还没有在内存中生成,知道它被调用。Python做了如下的操作:
1)Foo中有__metaclass__这个属性吗?如果是,Python会在内存中通过__metaclass__创建一个名字为Foo的类对象(我说的是类对象)。
2)如果Python没有找到__metaclass__,它会继续在父类中寻找__metaclass__属性,并尝试做和前面同样的操作。
3)如果Python在任何父类中都找不到__metaclass__,它就会在模块层次中去寻找__metaclass__,并尝试做同样的操作。
4)如果还是找不到__metaclass__,Python就会用内置的type来创建这个类对象。

现在的问题就是,你可以在__metaclass__中放置些什么代码呢?

答案就是:可以创建一个类的东西。那么什么可以用来创建一个类呢?type,或者任何使用到type或者子类化type的东西都可以。说白了每个类在定义时就已经通过type或者子类化type的东西创建了类对象。


二.自定义元类

元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过设定__metaclass__。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。

__metaclass__实际上可以被任意调用,它并不需要是一个正式的类。所以,我们这里就先以一个简单的函数作为例子开始。

# 自定义元类,使得由该元类创建的类所有参数都是大写,即使定义小写,也给变成大写<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# 元类会自动将你通常传给‘type’的参数作为自己的参数传入
def upper_attr(future_class_name, future_class_parents, future_class_attr):
    '''返回一个类对象,将属性都转为大写形式'''
    # 选择所有不以'__'开头的属性
    attr = {}
    for name, value in future_class_attr.items():
        if not name.startswith('__'):
            # 将它们转为大写形式
            attr[name.upper()] = value
    # 通过'type'来做类对象的创建
    return type(future_class_name, future_class_parents, attr)  # 返回一个类


class Foo(object, metaclass=upper_attr):
    # __metaclass__ = upper_attr

    def __init__(self):
        pass
    bbb = 'a'
    __bbb = 'a'
foo = Foo()
print(hasattr(Foo, 'bbb'))
# 输出: False
print(hasattr(Foo, 'BBB'))
# 输出:True

print(hasattr(Foo, '__bbb'))
# 输出: False
print(hasattr(Foo, '__BBB'))
# 输出:False
结果:
False
True
False
False



猜你喜欢

转载自blog.csdn.net/weixin_31449201/article/details/80320672