对象是Python组织数据的形式,所有的数据都是对象(object),即某个类(Class)的instance。即便是整数,甚至整数常量这种简单的数据类型(其类为)。每个对象都有ID(identity),类型(type)和值(value)。这三者中,只有value是可以变化的,另外两个都是不可变的。
ID可以被视为对象在内存中的位置,内嵌函数id()返回了对象的ID,而is操作符则比较了两个对象的ID是否一致。type()返回了对象的类型(即所属的类Class):type(3)==int,除了常量之外(变量、类、包等)也可以用xxx.__class__得到同样结果
而类型本身也是一个对象,其类型是“type”:type(type(3))==type
"type"的所属类型也是"type":type(type(type(3)))==type
某些对象包含了其他对象(的引用),它们被称为容器(Container),比如list,tuple,dict等,这些引用是容器的值的一部分。
下文中:类、类型、type、class同义
对象、实例、object、instance同义
(1)类的层次
对象的类型(type)即其所属的类(class),这也决定了该对象所能支持的操作。内嵌函数type(object)可以得到对象所属的类。
类的层次关系:NoneType:只有一个对象,值唯一,即None
NotImplementedType:只有一个对象,值唯一,即NotImplemented
ellipsis:
numbers.Number:numbers.Integral:整数Integers:即int类型
Booleans:即bool类型
numbers.Real:即float类型
numbers.Complex:即complex类型
Sequences:有序的有限元素的集合,其元素可以用非负整数索引(即从0开始)不可变Sequences:创建之后不可修改Strings:即str类型,可通过str.encode()函数编码为bytes类型
Tuples:即tuple,元组类型
Bytes:即bytes类型,可通过bytes.decode()函数变为str类型
可变Sequences:创建之后可以修改Lists:即list类型
Byte Arrays:即bytearray类型,与bytes类型的区别在于可以修改
Set类型:无序的,有限元素的集合,可len(),可iter()Sets:可变集合,通过set()创建
Frozen Sets:不可变的集合,通过frozenset()创建,可hash()
Mappings:映射,目前只有字典一个子类字典类:即dict类型
Callable类型:可调用的类型自定义函数:用户通过def定义
实例方法:
generator函数:使用yield语句的函数
Coroutine函数:协程函数
异步generator函数:
built-in function:内嵌函数
built-in method:内嵌方法
Class:就是类,所有的类都是可调用的,返回该类的对象
class instance:类的实例,可以通过实现__call__()来变得可调用
模块:Python中的模块都是module类的对象
Custom classes:
Class instance:
I/O objects:
Internal types:Code objects:
Frame objects:
Traceback objects:
Slice objects:
Static method objects:
Class method objects:
参考:3. Data model - Python 3.9.1 documentationdocs.python.org
(2)类==对象
定义某个类的一个对象,可以用如下语句:
object = class(args...)
比如:
a = int(4)
或者
b = list([1,2,3])
由于Python中所有的类也都是对象,因此这里的class()相当于class.__call__(),即一个object的可调用函数:
a = int.__call__(4)
b = list.__call__([1,2,3])
Python中所有的类也都是对象,而这些对象的类型是type,或者说,所有类都是‘type’的实例(包括type本身也是type的实例),如此一来,定义一个新的类,相当于:
class = type(classname, superclass, attributedict)
或者
class =type.__call__(classname, superclass, attributedict)
例如:
class NewClass:
data = 1
相当于:
NewClass = type(“NewClass”, (), {‘data’:1})
相当于:
NewClass = type.__call__(“NewClass”, (), {‘data’:1})
type被是一个metaclass,即元类。
(3)metaclass
元类(metaclass)的对象是普通类,但是普通类的类可以不是‘type’,也就时说除了‘type’还可以定义其他的metaclass(通常这些metaclass的类型也是‘type’)。
定义新的metaclass,并将类的元类设置为这个新metaclass的目的,通常是为了修改创建类的对象时的过程。
在类的定义中,通过声明metaclass=MyMeta,会使得:在生成类的时候,如果有,MyMeta的__new__()和__init__()会被调用
在生成类的对象时,如果有,MyMeta类的__call__()替代type.__call__()被调用:
例如:
class Foo(metaclass=MyMeta)
会依次调用以下函数来创建Foo:
1. type.__call__():MyMeta的类型是‘type’
(1) MyMeta.__new__()
(2) MyMeta.__init__()
foo = Foo()
会依次调用如下函数来创建Foo的实例foo:
1. MyMeta.__call__()
(1) Foo.__new__()
(2) Foo.__init__()
注意混淆:
声明某个类的元类在Python3的用法是:
class Foo(metaclass=MyMeta)
在python2.7的用法则是如下:
class Foo:
__metaclass__=MyMeta
注意混淆:
注意区分“父类-子类”和“类型-对象”的关系,父类-子类能构成若干层的继承结构,但是(在不指定metaclass的情况下)所有这些类的类型都是‘type’,而子类和父类的元类可以不同,简单来说,这是两个不同维度的概念。
参考:somenzz:一文搞懂什么是Python的metaclasszhuanlan.zhihu.comPython 元类 (MetaClass) 小教程lotabout.me__metaclass__方法 - rookiehbboy - 博客园www.cnblogs.com
(4)生成实例的过程
我们知道,如果类Foo的定义中有__call__函数的实现,则Foo的对象foo是可以调用的,即:
foo()
相当于调用foo所属类Foo的__call__函数:
Foo.__call__()
而当一个类Foo的对象foo生成的时候,发生的函数调用是这样的:
foo = Foo()
1. 调用Foo的所属类型的__call__:type.__call__()
(1) 调用Foo的__new__函数:Foo.__new__()
(2) 调用Foo的__init__函数:Foo.__init__()
当定义一个metaclass MyMeta的时候:
class MyMeta(type):
相当于:
MyMeta = type(“MyMeta”, ...)
1. 调用type所属类型(仍是type)的__call__:type.__call__()
(1) 调用type的__new__函数:type.__new__()
(2) 调用type的__init__函数:type.__init__()
当定义一个metaclass为MyMeta的类的时候:
class Foo(metaclass=MyMeta):
相当于:
Bar = MyMeta(“Bar”, ...)
1. 调用MyMeta所属类型(type)的__call__函数:type.__call__()
(1) 调用MyMeta的__new__函数:MyMeta.__new__()
(2) 调用MyMeta的__init__函数:MyMeta.__init__()
当生成Bar的对象bar的时候:
bar = Bar()
1. 如果Bar的所属类型MyMeta有定义__call__,则调用:MyMeta.__call__()
(1) 如果其中调用了self.__new__函数,则调用:Bar.__new__()
(2) 如果其中调用了self.__init__函数,则调用:Bar.__init__()
2. 否则,则调用type.__call__()
(1) 调用type的__new__函数:type.__new__()
(2) 调用type的__init__函数:type.__init__()