• 11 元类


    1. 类也是对象

    class Person(object):
        num  = 0 
        print("---person class")
    
        def __init__(self):
            self.name = "abc"
    
    print("hello world")
    print(Person)
    
    
    ### 结果
    ---person class
    hello world
    <class '__main__.Person'>

    2. 动态地创建类

    >>> def choose_class(name):
    …       if name == 'foo':
    …           class Foo(object):
    …               passreturn Foo     # 返回的是类,不是类的实例else:
    …           class Bar(object):
    …               passreturn Bar
    …
    >>> MyClass = choose_class('foo')
    >>> print MyClass              # 函数返回的是类,不是类的实例
    <class '__main__'.Foo>
    >>> print MyClass()            # 你可以通过这个类创建类实例,也就是对象
    <__main__.Foo object at 0x89c6d4c>

     但这还不够动态,因为你仍然需要自己编写整个类的代码。由于类也是对象,所以它们必须是通过什么东西来生成的才对。当你使用class关键字时,Python解释器自动创建这个对象

    3. 使用type创建类

    type还有一种完全不同的功能,动态的创建类。

    type可以接受一个类的描述作为参数,然后返回一个类。(要知道,根据传入参数的不同,同一个函数拥有两种完全不同的用法是一件很傻的事情,但这在Python中是为了保持向后兼容性)

    type可以像这样工作:

    type(类名, 由父类名称组成的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))

    #### class Test
    In [1]: class Test:
       ...:     pass
       ...: 
    
    In [2]: t1 = Test()
    
    
    ### type 创建Test2类
    In [3]: Test2 = type("Test2",(),{})
               #type(类名, 父类(元组),属性(字典)                
    In [4]: t2 = Test2()
    
    In [5]: type(t1)
    Out[5]: __main__.Test
    
    In [6]: type(t2)
    Out[6]: __main__.Test2

      实例对象是class对象创建的,class是type创建的,type就是元类

      最元始创建类的东西,就是元类

      1)创建带属性的类

    In [7]: Person2 = type("Person2",(),{"num":0})
                                                              #带有属性的
    In [8]: p2 = Person2()
    
    In [9]: p2.num
    Out[9]: 0

      2)带有方法的类

    In [10]: def printNum(self):
       ....:     print("---num -- %d"%self.num)
       ....:     
    
    In [11]: Test3 = type("Test3",(),{"printNum":printNum})
    
    In [12]: t3 = Test3()
    
    In [15]: t3.num = 100
    
    In [16]: t3.printNum()
    ---num -- 100
    ### 等价的
    In [17]: class printNum2:
       ....:     def printNum(self):
       ....:         print("---num-%d"%self.num)
       ....:         
    
    In [18]: t2 = printNum2()
    
    In [19]: t2.num = 100
    
    In [20]: t2.printNum()
    ---num-100

      3)带有继承的类

    In [21]: class Animal(object):
       ....:     def eat(self):
       ....:         print('---eat--')
        
    
    ## 创建个狗类
    In [23]: class Dog(Animal):
       ....:     pass
    
    
    In [25]: wangcai = Dog()
    
    In [26]: wangcai.eat()
    ---eat--
    
    
    ##创建个猫类
    In [27]: Cat = type("Cat",(Animal,),{})
    In [28]: tom = Cat()
    
    In [29]: tom.eat()
    ---eat--

    4. 到底什么是元类(终于到主题了)type

    元类就是用来创建类的“东西”。你创建类就是为了创建类的实例对象,不是吗?但是我们已经学习到了Python中的类也是对象。

    元类就是用来创建这些类(对象)的,元类就是类的类,你可以这样理解为:

    Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来,这个类就是type。

        

    #type就是Python在背后用来创建所有类的元类
    #你可以通过检查__class__属性来看到这一点
    
    In [31]: wangcai.__class__
    Out[31]: __main__.Dog
    
    In [32]: tom.__class__
    Out[32]: __main__.Cat
    
    
    In [33]: Cat.__class__
    Out[33]: type
    
    In [30]: Dog.__class__
    Out[30]: type
    
    
    In [34]: type.__class__
    Out[34]: type

    5. 自定义元类

    python2中  __metaclass__ = upper_attr
    #-*- coding:utf-8 -*-
    def upper_attr(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
    
        #调用type来创建一个类
        return type(future_class_name, future_class_parents, newAttr)
    
    class Foo(object):
        __metaclass__ = upper_attr #设置Foo类的元类为upper_attr
        bar = 'bip'
    
    print(hasattr(Foo, 'bar'))
    print(hasattr(Foo, 'BAR'))
    
    f = Foo()
    print(f.BAR)
    python3中  class Foo(object, metaclass=upper_attr):
    #-*- coding:utf-8 -*-
    def upper_attr(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
    
        #调用type来创建一个类
        return type(future_class_name, future_class_parents, newAttr)
    
    class Foo(object, metaclass=upper_attr):
        bar = 'bip'
    
    print(hasattr(Foo, 'bar'))
    print(hasattr(Foo, 'BAR'))
    
    f = Foo()
    print(f.BAR)
  • 相关阅读:
    To My Girlfriend (DP)
    A Simple Nim (SG打表找规律)
    A Boring Question (打表)
    A Simple Chess (Lucas组合数 + 容斥)
    World is Exploding (容斥 + 统计)
    Two (DP)
    K-wolf Number (数位DP)
    Interesting (manacher + 前缀和处理)
    How Many Triangles (极角排序 + 尺取法)
    Divide the Sequence (贪心)
  • 原文地址:https://www.cnblogs.com/venicid/p/7941195.html
Copyright © 2020-2023  润新知