元类和__metaclass__

# python 里面一切都是对象!!函数是对象、变量是对象、类也是对象
# 实例对象是由类创建的,1是由int类创建的,"haha"是由str类创建的,类是由元类创建的!!!
# 元类是创建类的类(类是type类的实例)(当解释器遇到class关键字的时候,就创建出了这个类对象)

# 一下展示一下这些对象是由什么类创建的
print("haha".__class__)
print(type("haha"))

list = [1, 2, 3, 4]
print(type(list))
print(list.__class__)


class test01(object):
    pass


obj = test01()
print(type(obj))
print(type(test01))
print("*" * 60)


# 动态地创建类
# 使用type()内建函数动态地创建类(内建函数type()有两种功能!在设计上是非常蠢的,但是为了保持python的版本向上兼容性)
# type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
# 使用type创建带有属性和方法的类
def show(self):
    print("this count is %d" % (self.count))


# 带有静态方法
@staticmethod
def run():
    print("我只想奔跑,没有self")


# 带有类方法
@classmethod
def addCount(cls):
    cls.count += 1


# 这一句是创建了一个类(name和age是这个类的类属性)
test02 = type("test02", (), {"count": 1, "show": show, "run": run, "addCount": addCount})
# 这一句是创建类test02的实例对象
t1 = test02()
print(t1.count)
t1.show()
t1.run()
t2 = test02()
t2.addCount()
t2.show()
print("*" * 60)


# 自定义元类
# __metaclass__属性
# class Foo(object):
#     __metaclass__ = something…
#     ...省略...
# 一个类是怎么被创建的????python解释器看到class关键字的时候,并没有在内存中这个类,而是在寻找__metaclass__这个属性,
# 在本类中找不到就到父类中找,如果都找不到,就使用内置的type()来创建这个类
# 我们通过重写__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)


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


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

f = Foo()
print(f.BAR)
# 输出:'bip'

# 元类其实用的特别特别少!!
# 拦截类的创建
# 修改类
# 返回修改之后的类

 

posted @ 2018-11-12 21:32  人工智能之路上的菜鸡  阅读(163)  评论(0编辑  收藏  举报