理解python中的元类(metaclass)

本文是根据stackoverflow上关于“What are metaclasses in Python?”的回答翻译总结而成的。原数据连接:
https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

1. 类对象(class as object)

在了解元类(metaclass)之前, 首先得熟悉一下python中的类(class)。python对于什么是类有一个很独特的定义,借鉴与Smalltalk编程语言。

在很多编程语言中,类仅仅是一段用来描述如何产生对象的代码。python中的类也有这种功能。
>>> class ObjectCreator ( object ):
    ... pass ...
>>> my_object = ObjectCreator ()
>>> print ( my_object )
< __main__ . ObjectCreator object at 0x8974f2c >

但是,在python中,类的作用远不止这个。
类本身也是对象。
因为类是对象,所以我们可以对其进行很多操作:
  • 赋值给一个变量
  • 复制类
  • 添加属性
  • 作为参数传递给函数
>>> class ObjectCreator ( object ):
...     pass
...
>>> print ( ObjectCreator ) # you can print a class because it's an object
< class '__main__.ObjectCreator'
> >>> def echo ( o ):
...       print ( o )
...
>>> echo ( ObjectCreator ) # you can pass a class as a parameter
< class '__main__.ObjectCreator'
> >>> print ( hasattr ( ObjectCreator , 'new_attribute' ))
False
>>> ObjectCreator . new_attribute = 'foo' # you can add attributes to a class
>>> print ( hasattr ( ObjectCreator , 'new_attribute' ))
True
>>> print ( ObjectCreator . new_attribute )
foo
>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable
>>> print ( ObjectCreatorMirror . new_attribute )
foo
>>> print ( ObjectCreatorMirror ())
< __main__ . ObjectCreator object at 0x8997b4c >

2. 动态创建类(Creating classes dynamically)

由于类是对象,所以你可以在任何地方创建它们,就像其他类型对象一样。
例如,在一个函数内通过class关键字创建类:
>>> def choose_class ( name ):
...       if name == 'foo' :
...           class Foo ( object ):
...               pass ...  
            return Foo # return the class, not an instance
...       else :
...           class Bar ( object ):
...               pass
...           return Bar
...
>>> MyClass = choose_class ( 'foo' )
>>> print ( MyClass ) # the function returns a class, not an instance
< class '__main__.Foo'
> >>> print ( MyClass ()) # you can create an object from this class < __main__ . Foo object at 0x89c6d4c >

但是这并不是动态地创建类,因为你还是需要把类的整体写出来。
既然类是对象,那么它肯定是由什么东西生成的。这就引出了元类——用来创建类的‘东西’


3.  元类是一个类(class)对象

普通的类定义了该类的实例对象所具有的属性和方法,元类就定义了普通类所具有的属性和方法。即实例对象是普通类的实例化,普通类是元类的实例化。如下图所示:


Python中一切皆对象(object)。对象包括了数字(int), 字符串(string), 函数(functions)和类(class)。这些对象都需要通过调用元类来构建,所以元类通常被用作类工厂(class-factory)。 例如,我们通过调用类来创建类的实例,python中通过调用元类来创建一个新的类。结合__init__和__new__方法,元类就允许你在创建新类是添加一些额外的内容,甚至是完全重载该类。

除了类工厂外,元类还定义了类的类型(type),所以你可以用它来做更多的事情。例如,给元类定义一些常规的方法。元类中的方法(metaclass-method)就像是类方法(classmethod),所以你可以直接通过类名来调用这些方法,而不需要通过实例来调用。事实上,通过实例是无法调用元类中的方法的。这也是元类中方法与类方法的区别。


4.  __metaclass__属性

当我们创建类时,可以在类的定义中添加__metaclass__属性。属性值是一些创建类的操作。
class Foo(object):
__metaclass__ = something...
[...]
添加完后,python就会用元类来创建类Foo。
注意,整个过程其实是这样的:
  • 首先当你输入 class Foo(object)后,类Foo并没有在内存中被创建。python会在类Foo的定义中寻找__metaclass__。
  • 如果找到了,则就会使用__metaclass__来创建类。
  • 如果没有找到,就会调用type来创建类。

4. type

type是Python中常见的一个元类。你没有听错,type是一个类(以前我一直以为type是一个内置函数呢!),用来构建类对象。所以type(type)返回的是class type。类似的元类还有str和int, 分别用来构建字符串对象和整数对象。他们都有__class__属性,值为class ‘type’

>>> type(type)
<class 'type'>
>>> str.__class__
<class 'type'>
>>> int.__class__
<class 'type'>

除了返回对象的类型外,type还有一个截然不同的功能——动态创建类。type接受对类的描述作为参数,然后返回一个类。
例如:
>>> MyShinyClass = type ( 'MyShinyClass' , (), {}) # returns a class object
>>> print ( MyShinyClass )
< class '__main__.MyShinyClass'
> >>> print ( MyShinyClass ()) # create an instance with the class
< __main__ . MyShinyClass object at 0x8997cec >
type可以通过传入字典参数来定义类的属性。
>>> Foo = type ( 'Foo' , (), { 'bar' : True })
上述代码等同于:
>>> class Foo ( object ):
...     bar = True
type产生的类支持一切类的操作,包括继承。
>>> print ( Foo )
< class '__main__.Foo'
> >>> print ( Foo . bar )
True
>>> f = Foo ()
>>> print ( f )
< __main__ . Foo object at 0x8a9b84c
> >>> print ( f . bar ) True

>>> FooChild = type ( 'FooChild' , ( Foo ,), {})
等价于
>>> class FooChild ( Foo ):
...       pass

5. 结语

类是对象,可以用来创建实例。而类本身又是元类的实例。
python中一切皆为对象,所有的对象都是类的实例或者元类的实例。
type是一个例外。type是其自身的元类。它是定义在解析器层面上的,不是你通过纯python代码可以复制的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python元类metaclass)是用于创建的“”。元类定义了的行为和特征。当我们使用关键字class创建一个时,Python实际上在幕后使用元类来实现这个过程[1]。元类Python一个非常强大且复杂的概念。 在Python,一切都是对象,它们要么是的实例,要么是元类的实例,除了type。type实际上是它自己的元类,在纯Python环境无法直接创建自定义元类。然而,通过一些技巧,我们可以使用type作为基来创建元类理解元类之前,首先需要掌握Python的概念。在大多数编程语言是用来描述如何生成对象的代码段。在Python也是如此,我们可以通过使用关键字class来定义一个,并通过来创建对象。例如: ``` class ObjectCreator(object): pass my_object = ObjectCreator() print(my_object) ``` 上述代码定义了一个名为`ObjectCreator`的,然后通过调用来创建了一个对象。打印`my_object`会显示对象的内存地址。 元类可以用于修改的行为。通过定义自己的元类,我们可以在创建时对其进行定制化的修改。一种常见的使用元类的方式是在添加额外的属性、方法或者修改的继承关系。 除了使用元类之外,还有两种常用的技术来修改:Monkey Patching和装饰器。Monkey Patching是在运行时对进行修改,即在不改变定义的情况下,通过给添加新的属性或方法来扩展的功能。装饰器则是在定义之前对进行修改,通常是通过在定义前应用一个装饰器函数,该函数可以对进行修改或包装。 总结来说,元类Python是用于创建。通过使用元类,我们可以在的创建过程对其进行定制化的修改。此外,Python还提供了其他两种技术来修改:Monkey Patching和装饰器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值