zoukankan      html  css  js  c++  java
  • 元类和__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'
    
    # 元类其实用的特别特别少!!
    # 拦截类的创建
    # 修改类
    # 返回修改之后的类
  • 相关阅读:
    对MVC模型的自悟,详尽解释,为了更多非计算机人员可以理解
    openSUSE leap 42.3 实现有线 无线同时用
    Fedora27 源配置
    Ubuntu16.04添加HP Laserjet Pro M128fn打印机和驱动
    openSUSE leap 42.3 添加HP Laserjet Pro M128fn打印机和驱动
    OpenSUSE Leap 42.3下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    OpenSUSE Leap 42.3 安装java(Oracle jre)
    linux下支持托盘的邮件客户端Sylpheed
    Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
    Firefox 浏览器添加Linux jre插件
  • 原文地址:https://www.cnblogs.com/tangxlblog/p/9949262.html
Copyright © 2011-2022 走看看