python-面向对象-07类对象/元类metaclass

Rosalia ·
更新时间:2024-11-10
· 836 次阅读

1.引题

类对象?是什么鬼?对象不是类的实例么,那类对象是什么意思?在Python中,普通类既是一个类,但同时也是一个对象(也叫做类对象),对的,你没有看错。不信?我们看一个例子。

class Student: pass # 空语句 # 实例化对象 s1 = Student() print("对象s1的id和type和__class__") print(id(s1)) print(type(s1)) print(s1.__class__) print("--" * 10) print("类Student的id和type和__class__") print(id(Student)) print(type(Student)) print(Student.__class__)

执行结果:

对象s1的id和type 4489106320 -------------------- 类Student的id和type 140254813901664

通过执行结果可以看到:

首先对象s1和类Student的id值,也就是存储的内存地址,数值相差比较大,至少说明对象和类是分区域存储的。 在python3中type函数和__class__的效果相同,也就是说在python3中这两者是一致(后面有补充说明)。 __class__属性会指向该实例对应的类,类Student的__class__属性值为,由此我们可以知道类Student是类type的实例。从这个角度上来说,普通类也是一个对象。 2.Metaclasses登场

Metaclasses中文名称是元类,元类是一个深奥的OOP概念,隐藏在几乎所有Python代码背后。不管你是否意识到,你都在使用它们。在大多数情况下,你不需要意识到它。大多数Python程序员很少(如果有的话)需要考虑元类。

在我自己的实际工作中几乎没有特意使用过元类。

python之禅的作者Tim Peters对于Metaclasses的描述:

“Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t (the people who actually need them know with certainty that they need them, and don’t need an explanation about why).”

译文:

元类的魔力比99%的用户所担心的都要深。如果你想知道你是否需要它们,你不需要(真正需要它们的人肯定知道他们需要它们,不需要解释为什么)。

— Tim Peters

我第一次看到这句话的时候,也有一些蒙圈。下面我们就一步一步来揭开Metaclasses的神秘面纱。

3.旧式类和新式类

在Python领域中,类可以是两种变体之一。官方的术语对于这一部分还没有确定,所以它们被非正式地称为旧式和新式类。

3.1 旧式(Old-Style)类

对于旧式的类,类和类型不是完全相同的东西。旧式类的实例总是由一个称为instance的内置类型实现。如果obj是一个旧式类的实例,那么obj.__class__指向具体的类,但类型(obj)总是instance。下面的例子摘自Python 2.7命令行:

>>> import sys >>> print sys.version 2.7.16 (default, Dec 13 2019, 18:00:32) [GCC 4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.32.4) (-macos10.15-objc-s >>> class Foo: ... pass ... >>> x = Foo() >>> x.__class__ >>> type(x) 3.2 新式(New-Style)类

在python3中,新型的类统一了类和类型的概念。如果obj是一个新样式类的实例,那么type(obj)与obj._ class__是相同的,均为class,不在继续使用instace.

>>> import sys >>> sys.version '3.7.7 (v3.7.7:d7c567b08f, Mar 10 2020, 02:56:16) \n[Clang 6.0 (clang-600.0.57)]' >>> class Foo: ... pass ... >>> obj = Foo() >>> obj.__class__ >>> type(obj) >>> obj.__class__ is type(obj) True 3.3 新式类和旧式类总结

在python2中,类默认是旧式类。在python2.2版本之前,新式类根本不支持。在python2.2以及后续的python2版本中,能够创建新式类,但是必须指定为新式类。
在python3中,所有的类默认是新式类。因此,在python3中,type(类)类.__class__是一致的。

4 类和类型 4.1 代码分析

还是用我们刚才使用的例子进行分析

>>> class Foo(): ... pass ... >>> x = Foo() >>> type(x) >>> type(x)

在这个例子中:

对象x是类Foo的实例。 类Foo是type元类(metaclass)的实例。 type元类也是type元类(metaclass)的实例,所以type元类是自身的一个实例。

原创文章 13获赞 10访问量 381 关注 私信 展开阅读全文
作者:聂发俊



对象 类对象 面向对象 Python

需要 登录 后方可回复, 如果你还没有账号请 注册新账号