zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/venicid/p/7941195.html
Copyright © 2011-2022 走看看