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)

 

posted @ 2017-12-01 11:33  venicid  阅读(159)  评论(0编辑  收藏  举报