python元类


我们class定义一个类,实例化产生对象:

class People:
    pass


p1 = People()

# python 一切皆对象,p1是People实例化的,那People这个类也是对象,People是哪个类产生的?
print(type(p1))

# <class '__main__.People'>

print(type(People))

# <class 'type'>

type函数可以用来看产生对象的类,可以看到我们class定义的类默认是type这个类实例化的对象

产生类的两种方式

class定义类

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

    def talk(self):
        print('talking')

# print(Chinese)
# <class '__main__.Chinese'>

调用元类type产生

class_name = 'Chinese'  # 类名
class_bases = (object,)  # 继承父类
class_body = '''  
country = 'china'
def __init__(self, name, age):
    self.name = name
    self.age = age
def talk(self):
    print('talking')

'''  # 类的内容
class_dict = {}

exec(class_body,globals(),class_dict)  # 为类产生局部名称空间

# print(class_dict)
# {'country': 'china', '__init__': <function __init__ at 0x000001ABF45FC1E0>, 'talk': <function talk at 0x000001ABF65D8BF8>}


C = type(class_name,class_bases,class_dict)  # 调用type产生类

# print(C)
# <class '__main__.Chinese'>

自定义元类

自定义元类控制类的创建

自定义元类其实就是创建一个继承元类type 的类,以此作为元类实例化创建类。
之前我们看到调用type元类传入了三个参数,
C = type(class_name,class_bases,class_dict)
那我们自定义元类之后也要传入这三个参数,不用管内部怎么处理,继承元类type的功能就行。我们可以添加条件控制以此为元类创建的类的行为。

# C = type(class_name,class_bases,class_dict)

# 创建一个继承元类type的类
class Test(type):  # 继承元类type的属性
    def __init__(self, class_name, class_bases, class_dict):
        if not class_name.istitle():  # 加入条件
            raise TypeError('首字母大写')

        super(Test, self).__init__(class_name, class_bases, class_dict)


class Chinese(metaclass=Test):
    def __init__(self, name,age):
        self.name = name
        self.age = age

    def talk(self):
        print('talking')


print(Chinese)
# <class '__main__.Chinese'>



class people(metaclass=Test):
    pass


print(people)
# TypeError: 首字母大写

或者直接调用type__new__方法:

class Test(type):  # 继承元类type的属性
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls,*args,**kwargs)


class Chinese(metaclass=Test):
    def __init__(self, name,age):
        self.name = name
        self.age = age

    def talk(self):
        print('talking')


# print(Chinese)
# <class '__main__.Chinese'>

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

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

    def __call__(self, *args, **kwargs):
        print(self,args,kwargs)


p1 = People('小明', 18)
p1('a','b',num='18')
# <__main__.People object at 0x000001DD97AD9208> ('a', 'b')

如果我们定义一个类,类中有__call__方法,那实例化产生的对象可以调用 p1(‘a’,‘b’,num=‘18’),
同样的,反之推导,如果我们把类People看作是元类产生的对象,既然我们可以调用People(‘小明’, 18)那么元类中应该有__call__方法,既然如此,我们可以看作调用People(‘小明’, 18)实例化产生的对象p1就可以看作是元类中调用__call__方法的返回值

class Test(type):
    def __init__(self, class_name, class_bases, class_dict):
        super(Test,self).__init__(class_name, class_bases, class_dict)

    def __call__(self, *args, **kwargs):  # 实例化时的属性值,self = People,参数:'小明',18
        obj = object.__new__(self)  # 产生空对象obj
        self.__init__(obj, *args, **kwargs)  # self= People, 转到People.__init__(self, name, age):
        return obj  # 返回obj


class People(object, metaclass=Test):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print('running')

p1 = People('小明',18)

示例

比如要求实例化时参数必须用关键字形式,自定义产生的属性必须大写:

class Test(type):
    def __new__(cls, *args, **kwargs):
        return type.__new__(cls, *args, **kwargs)

    def __call__(self, *args, **kwargs):
        if args:
            raise TypeError
        obj = object.__new__(self)

        for k,v in kwargs.items():
            obj.__dict__[k.upper()]=v
        return obj


class People(metaclass=Test):
    def talk(self):
        print('talking')


p1 = People(name='小明')

# print(p1.__dict__)
# {'NAME': '小明'}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值