• 理解Python中的元类


    1.引入

    Python中一切皆对象,所谓对象就是由类创建出来,那么创建对象的类本身也是一个对象,也就是说创建对象的类本身也由别的什么类创建,这种创建类的类就叫元类.

    2.元类是谁?

    type函数就是元类,没错就是那个打印数据类型的函数,也就是说是type创建了类.

    我们写一个类然后打印一下他的属性看看

    In [4]: class MyClass(object): 
       ...:     pass 
       ...:                                                                                           
    
    In [5]: type(MyClass)                                                                             
    Out[5]: type
    

    可以看到MyClass类的类型是type,用Python语言来描述这种关系就是:

    MyClass = type()
    

    3.typeobject的区别

    刚接触元类时很容易搞混这两者.区别如下

    type是说有类的创建者

    object是所有类的父类

    怎么理解呢?记住以下几点就OK了(可能有点绕)

    • typeobject不是同一层的东西
    • type是元类object是普通类
    • 元类的对象是普通类,普通类的对象就是普通对象
    • 继承自object的类包括object本身都是普通类
    • 继承自type的类都是元类
    • 普通类都是元类的对象
    In [9]: type(object)                                                                              
    Out[9]: type
    

    那么是谁创建了type呢?这个问题留给你们自己去找答案,我相信有很多小伙伴已经猜到了.

    3.通过type创建普通类

    type创建普通类的格式为

    变量名 = type("类名", ("继承的类",), {"属性名":"属性值"})
    

    第二个参数是元组类型

    举个例子

    In [11]: Myclass = type("ClassName", (object,), {"name": "kainhuck", "foo":"bar"})                
    
    In [12]: Myclass                                                                                  
    Out[12]: __main__.ClassName
    

    可以看到Myclass不是真正的类名,真正的类名是ClassName.

    创建一个名为ClassA,继承自object类,并带有属性name和方法printName的类,写法如下

    In [15]: def printName(self): 
        ...:     print(self.name) 
        ...:                                                                                          
    
    In [16]: ClassA = type("ClassA",(object,),{"name":"myName", "printName":printName})               
    
    In [17]: a = ClassA()                                                                             
    
    In [18]: a.printName()                                                                            
    myName
    
    

    4.创建自己的元类

    前面已经有过提示,我们可以通过继承type来创建自己的元类

    举个例子:

    In [20]: class MetaClass(type): 
        ...:     pass 
        ...:                                                                                          
    
    In [21]: ClassA = MetaClass("ClassA",(object,),{"name":"myName", "printName":printName})          
    
    In [22]: a = ClassA()                                                                             
    
    In [23]: a.printName()                                                                            
    myName
    
    

    这个例子中我只继承type没有增加任何新的功能

    我们知道创建一个对象的功能由__new__函数实现,下面我们通过修改__new__函数来创建一个必须含有printName方法的类.

    In [30]: class MyMetaClass(type): 
        ...:     def __new__(cls, name, bases, attrs): 
        ...:         func = attrs.get("printName", None) 
        ...:         if not callable(func): 
        ...:             raise NotImplementedError("必须创建一个名为 printName 的函数") 
        ...:         return type.__new__(cls, name, bases, attrs) 
        ...:          
        ...:                                                                                          
    
    In [31]: ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":"not callable"})   
    ---------------------------------------------------------------------------
    NotImplementedError                       Traceback (most recent call last)
    <ipython-input-31-772aa102a27f> in <module>
    ----> 1 ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":"not callable"})
    
    <ipython-input-30-c2ffcc442a77> in __new__(cls, name, bases, attrs)
          3         func = attrs.get("printName", None)
          4         if not callable(func):
    ----> 5             raise NotImplementedError("必须创建一个名为 printName 的函数")
          6         return type.__new__(cls, name, bases, attrs)
          7 
    
    NotImplementedError: 必须创建一个名为 printName 的函数
    
    In [32]: ClassA = MyMetaClass("ClassA",(object,),{"name":"myName", "printName":printName})        
    
    In [33]:  
    

    可以看到如果我们定义的类没有创建printName函数就会报错.

    5.类工厂

    所谓类工厂就是生产类的地方,我们可以设计一个函数,使该函数可以通过参数来返回不同的类.

    男人和女人都是人,但是不同性别的人剪头发的时间不一样.我们就可以定义一个类工厂来按需求产生不同的类.

    def Person(sex):
        def manCut(self):
            print("我是男人,我剪头发很快")
    
        def womanCut(self):
            print("我是女人,我剪头发很慢")
    
        if sex == "man":
            return type("man", (object,), {"hairCut": manCut})
        elif sex == "woman":
            return type("woman", (object,), {"hairCut": womanCut})
        else:
            print("Error")
    
    Man = Person("man")
    Woman = Person("woman")
    
    lilei = Man()
    hanmeimei = Woman()
    

    out:

    我是男人,我剪头发很快
    我是女人,我剪头发很慢
    
  • 相关阅读:
    forms组件、cookie与session
    choices参数、MTV与MVC模型、Ajax、序列化组件、sweetalert搭建页面、自定义分页器
    Django 常用字段,数据库查询优化 only与defer
    django配置代码
    django 模板层、模型层
    Django 请求生命周期、路由层
    centos6.8安装httpd后无法访问
    初次认识dedecms和帝国cms内容管理系统
    遇到一个json解码失败的问题
    关于apache配置映射端口
  • 原文地址:https://www.cnblogs.com/kainhuck/p/11184707.html
Copyright © 2020-2023  润新知