• python的元类


    类是用来生成实例的模板,而元类则是用来生成类的模板。

    在 Python(以及其它语言)中,类本身就是可以被传递和自省的对象。正如前面所讲到的,既然可以用类作为模板来生成对象,那么用什么 作为模板来生成类呢?答案当然是 元类(metaclass)

    python 2.2+以后提供了一个称为type的特殊类,它是一个类工厂。

    使用type创建新类:

    >>> X = type('X', (), {'foo': lambda self: 'foo'})
    >>> X, X().foo()
    (<class '__main__.X'>, 'foo')

    X就是type创建的类。

    可以用来使用type的子类,来创建新类:

     1 class ChattType(type):
     2     def __new__(cls, name, bases, dct):    # __new__函数创建 3         # 在__new__方法里,cls是ChattType类本身
     4         # name是类的名称,字符串
     5         # bases是类的基类,一个tuple
     6         # dct是附件到类上的属性和方法,是一个字典
     7         
     8         print "Allocating memory for class", name
     9         print "cls is: ", cls
    10         print "name is: ", name
    11         print "bases is: ", bases
    12         print "dct is: ", dct
    13         print
    14         return type.__new__(cls, name, bases, dct)  # 创建类
    15     
    16     def __init__(cls, name, bases, dct):    # __init__函数初始化17         # 在__init__方法里,cls是已经创建好的类
    18         # name, bases, dct属性和__new__方法相同
    19     
    20         print "Initing class", name
    21         print "cls is: ", cls
    22         print "name is: ", name
    23         print "bases is: ", bases
    24         print "dct is: ", dct
    25         print
    26         super(ChattType, cls).__init__(name, bases, dct)
    27 
    28     def some_func(cls):
    29         print "cls is: ", cls
    30         print
    31         # 在这里,cls是已经生成好的类
    32         # 将类方法附件到生成的类上
    33         return "i am some_func in metaclass."
    34 
    35 X = ChattType('X', (), {'foo': lambda self: 'foo'})
    36 
    37 # 创建好的X类
    38 print X
    39 print
    40 
    41 # 类X的some_func方法
    42 print X.some_func()
    43 print
    44 
    45 # 类X的实例的foo方法
    46 print X().foo()
    47 print
    48 
    49 # 调用类X的实例的some_func方法会报错!!!
    50 print X().some_func()


    下面是运行结果:

    Allocating memory for class X
    cls is:  <class '__main__.ChattType'>
    name is:  X
    bases is:  ()
    dct is:  {'foo': <function <lambda> at 0x7f4f54b96668>}
    
    Initing class X
    cls is:  <class '__main__.X'>
    name is:  X
    bases is:  ()
    dct is:  {'foo': <function <lambda> at 0x7f4f54b96668>}
    
    <class '__main__.X'>
    
    cls is:  <class '__main__.X'>
    
    i am some_func in metaclass.
    
    foo
    
    Traceback (most recent call last):
      File "meta_class.py", line 53, in <module>
        print X().some_func()
    AttributeError: 'X' object has no attribute 'some_func'

    注意:

    在__new__方法中,第一个参数cls表示的元类的子类本身,就是ChattType。

    而在__init__方法中,第一个参数cls表示已经创建好的类。

     

    但是像下面这种情况下,在类中使用__new__则情况不同:

    class t(object):
       # __new__函数创建实例
    def __new__(cls, *args, **kwargs): print "cls is: ", cls print "args is: ", args print "kwargs is: ", kwargs #return super(t, cls).__new__(cls, *args, **kwargs) return object.__new__(cls, *args, **kwargs)

       # __init__函数初始化实例
    def __init__(self): print "init"

     

    运行结果:

    cls is:  <class '__main__.t'>
    args is:  ()
    kwargs is:  {}
    init

    在类的__new__方法里,cls参数是类本身。

     

  • 相关阅读:
    12.浏览器测试
    11.测试用例管理
    10.测试用例的钩子
    如何处理JSON中的特殊字符
    foreach的参数不是数组:Warning: Invalid argument supplied for foreach
    CI中的控制器中要用model中的方法,是统一写在构造器方法中,还是在每一个方法中分别写
    CodeIgniter配置之config
    **Apache Options指令详解
    .htaccess的基本作用及相关语法介绍
    .htaccess文件的作用(访问控制)
  • 原文地址:https://www.cnblogs.com/huazi/p/2796602.html
Copyright © 2020-2023  润新知