当前位置: 移动技术网 > IT编程>脚本编程>Python > day 28-1 元类

day 28-1 元类

2019年12月21日  | 移动技术网IT编程  | 我要评论

shay misuraca,隐私实录,hp打印机维修

元类

元类的用途:自定义元类控制类的创建行为及类的实例化行为

python 中一切皆为对象。

一切接对象,对象可以怎么用呢?

1、都可以被引用,x=obj

2、都可以当作函数的参数传入

3、都可以当作函数的返回值

4、都可以当作容器类的元素,l=[func,time,obj,1]

让我们先定义一个类,然后逐步分析

class people():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say(self):
        print('%s say welcome to here' % self.name)


p = people('ysg', 21)
p.say()
print(type(p))              # <class '__main__.people'>
print(type(people))         # <class 'type'>

所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化),比如对象t1是调用类oldboyteacher得到的

如果一切皆为对象,那么类 peope 本质也是一个对象,既然所有的对象都是调用类得到的,那么 peope 必然也是调用了一个类得到的,这个类称为元类

总结:产生类的类称之为元类,默认使用 class 定义的类,他们的元类是 type。

 

exec的用法

参数1:字符串形式的命令

参数2:全局作用域(字典形式),如果不指定默认就是用 globals()

参数3:局部作用局(字典形式),如果不指定默认就是用 locals()

例子

g = {
    'x': 'ysg',
    'y': '123'
}

l = {}

exec("""
global x,m
x = 'ysging'
m = 'pei'
z = '21'
""", g, l)
print(g)        # {'x': 'ysging', 'y': '123'..., 'm': 'pei'}
print(l)        # {'z': '21'}

 

元类定义的两种方式

方法一:class

class people():
    country = "china"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print('%s say good' % self.name)


p = people('ysg', '22')
print(people)                       # <class '__main__.people'>
print(p, p.name, p.age)             # <__main__.people object at 0x0000020b0fc652e8> ysg 22

方法二:type

定义类的三要素:类名、类的基类、类的名称空间

class_name = 'people'
class_bases = (object,)
class_body = """
country = "china"
def __init__(self, name, age):
    self.name = name
    self.age = age

def func(self):
    print('%s say good' % self.name)
"""
class_dic = {}
exec(class_body, globals(), class_dic)
people1 = type(class_name, class_bases, class_dic)
print(people1)                      # <class '__main__.people'>
p1 = people1('ysg', '22')
print(p1, p1.name, p1.age)          # <__main__.people object at 0x0000020b0fc65470> ysg 22

 

自定义元类控制类的创建行为

实现检索类名称是否为大写,类中是否写入注释

class mymeta(type):
    def __init__(self, class_name, class_bases, class_dic):
        super(mymeta, self).__init__(class_name, class_bases, class_dic)
        if not class_name.istitle():
            raise typeerror('类名称首字母要求大写')

        if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
            raise typeerror('新建的类必须标有注释')


class people(object, metaclass=mymeta):  # people = mymeta(class_name,class_bases,class_dic)
    '''
        使用自定义元类控制类的创建行为
    '''
    country = "china"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print('%s say good' % self.name)

 

自定义元类控制类的实例化行为

预备知识 __call__

class foo():
    pass


f = foo()
f()  # typeerror: 'foo' object is not callable
class foo():
    def __call__(self, *args, **kwargs):
        print(self)
        print(args)
        print(kwargs)


f = foo()
f(1, 2, 3, a=1, b=2, c=3)

结果:
<__main__.foo object at 0x000001dbe6b7f240>
(1, 2, 3)
{'a': 1, 'b': 2, 'c': 3}

由以上两个例子可以看出,在调用方式实际是自动调用了 __call__ 方法

所以可以得出,在使用元类控制类的实例化行为时:

  元类内部也应该有一个 __call__ 方法,会在调用 foo 时触发执行;foo(1,2,x=1) 就相当于 foo.__call__(foo,1,2,x=1)

 

  

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网