Python3 --- 元类

一、使用type创建类

type可以接受一个类的描述作为参数,然后返回一个类。如下:

Test = type('Test',(),{})
print(Test)
help(Test)

结果:

<class '__main__.Test'>
Help on class Test in module __main__:

class Test(builtins.object)
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)


二、使用type创建带有属性的类

type接受一个字典来为类定义属性,如下:

Dog = type('Dog',(),{'name':'二哈','age':1})
print(Dog)
help(Dog)

结果:

<class '__main__.Dog'>
Help on class Dog in module __main__:

class Dog(builtins.object)
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  age = 1
 |  
 |  name = '二哈'

三、使用type实现类的继承

Dog = type('Dog',(),{'name':'二哈','age':1})
print(Dog)
help(Dog)

DogChild = type('DogChild', (Dog,),{})
print(DogChild)
print(DogChild.name)

结果:

<class '__main__.Dog'>
<class '__main__.DogChild'>
二哈

四、使用type创建带有方法的类

#普通方法
def test(self):
    print("test")

#静态方法
@staticmethod
def static_test():
    print("static_test")

#类方法
@classmethod
def class_test(cls):
    print("class_test")

Test = type('Test',(),{'name':'name','test':test,'static_test':static_test,'class_test':class_test})
print(Test)

test = Test()
test.test()
test.static_test()
test.class_test()

结果:

<class '__main__.Test'>
test
static_test
class_test

五、元类

        元类的主要目的就是为了当创建类时能够自动地改变类。通常,你会为API做这样的事情,你希望可以创建符合当前上下文的类。

        假想一个很傻的例子,你决定在你的模块里所有的类的属性都应该是大写形式。有好几种方法可以办到,但其中一种就是通过在模块级别设定__metaclass__。采用这种方法,这个模块中的所有类都会通过这个元类来创建,我们只需要告诉元类把所有的属性都改成大写形式就万事大吉了。
        幸运的是,__metaclass__实际上可以被任意调用,它并不需要是一个正式的类。所以,我们这里就先以一个简单的函数作为例子开始。

class UpperAttrMetaClass(type):
    # __new__ 是在__init__之前被调用的特殊方法
    # __new__是用来创建对象并返回之的方法
    # 而__init__只是用来将传入的参数初始化给对象
    # 你很少用到__new__,除非你希望能够控制对象的创建
    # 这里,创建的对象是类,我们希望能够自定义它,所以我们这里改写__new__
    # 如果你希望的话,你也可以在__init__中做些事情
    # 还有一些高级的用法会涉及到改写__call__特殊方法,但是我们这里不用
    def __new__(cls, future_class_name, future_class_parents, future_class_attr):
        #遍历属性字典,把不是__开头的属性名字变为大写
        newAttr = {}
        for name,value in future_class_attr.items():
            if not name.startswith("__"):
                newAttr[name.upper()] = value

        # 方法1:通过'type'来做类对象的创建
        # return type(future_class_name, future_class_parents, newAttr)

        # 方法2:复用type.__new__方法
        # 这就是基本的OOP编程,没什么魔法
        # return type.__new__(cls, future_class_name, future_class_parents, newAttr)

        # 方法3:使用super方法
        return super(UpperAttrMetaClass, cls).__new__(cls, future_class_name, future_class_parents, newAttr)

#python2的用法
#class Foo(object):
#    __metaclass__ = UpperAttrMetaClass
#    bar = 'bip'

# python3的用法
class Foo(object, metaclass = UpperAttrMetaClass):
     bar = 'bip'

print(hasattr(Foo, 'bar'))
# 输出: False
print(hasattr(Foo, 'BAR'))
# 输出:True

f = Foo()
print(f.BAR)
# 输出:'bip'
就是这样,除此之外,关于元类真的没有别的可说的了。但就元类本身而言,它们其实是很简单的:
  • 拦截类的创建
  • 修改类
  • 返回修改之后的类


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值