对象,价值观和类型
Python的抽象的数据。 所有的数据在一个Python程序 表示对象或对象之间的关系。 (在某种意义上,在 符合冯诺依曼模型的代码也“存储程序计算机” 由对象。)
。 (不可变容器对象的价值 包含对一个可变对象的引用可以改变时,后者的价值 改变;然而容器仍然被认为是不可变的,因为 它包含的对象集合不能改变。 所以,不变性 严格一样有一个不变的值,它是更微妙的)。 一个 对象的可变性是由其类型,例如,数字、字符串 和元组是不可变的,而词典和列表是可变的。
对象是从来没有明确地摧毁了;然而,当他们成为遥不可及的 他们可能被垃圾收集。 一个实现允许推迟垃圾 收集或者干脆省略它——它是一种实现质量 垃圾收集是如何实现的,只要没有对象收集 仍可及。
CPython的实现细节: 模块控制循环垃圾的收集信息。 其他实现不同和CPython的可能变化。 不依赖于立即终结的对象,当他们成为 遥不可及的(例:总是关闭文件)。
声明可能保持 对象还活着。
”声明中提供便捷的方法。
。 容器的例子有元组、列表和字典。 的引用 集装箱的价值的一部分。 在大多数情况下,当我们谈论的价值 容器,我们暗示的值,而不是包含的对象的身份; 然而,当我们谈论一个容器的可变性,只有身份 立即包含的对象是隐含的。 所以,如果一个不可变的容器 (如一个元组)包含一个引用一个可变对象,如果它的值变化 可变的对象改变了。
)。
标准的类型层次结构
下面是一个列表的Python内置类型。 扩展模块 (写在C、Java或其他语言,根据实现) 定义额外的类型。 Python的未来版本可能添加类型的类型 层次结构(如。 整数、有理数高效存储阵列,等等), 尽管这样的增加将会提供通过标准库。
下面的一些类型描述包含一段特殊清单” 属性。 “这些属性实现和提供 不是用于一般用途。 它们的定义在未来可能会改变。
- 没有一个
-
。 它是用来表示 在很多情况下缺乏价值,如 从函数返回 不显式地返回任何东西。 它的真值是错误的。
- NotImplemented
-
。 数值方法 和丰富的比较方法可以返回这个值如果不实现 操作的操作数。 (翻译会试试的 反映操作,根据运营商或其他后备)。 它的 真值是正确的。
- 省略
-
。 它的真值是正确的。
- numbers.Number
-
这些都是由数字文本并返回结果的算术 运算符和算术内置函数。 数字对象是不可变的; 一旦创建它们的价值永远不会改变。 Python数字当然是强烈 与数学相关的数字,但数值的局限性 在电脑。
Python区分整数、浮点数和复杂 数字:
- numbers.Integral
-
这些代表元素从数学组整数(积极和 负面的)。
有两种类型的整数:
)
这些代表的数字在一个无限的范围内,可用(虚拟) 只有记忆。 为目的的转变和掩码操作,一个二进制 表示假设,负数表示的一个变体 2的补码赋予无限的幻想串标志位 扩展到左边。
- )
-
分别返回。
整数表示的规则是为了给最有意义的 解释涉及负整数的转变和掩模操作。
- )
-
这些代表机器双精度浮点数。 你是 的摆布底层机器体系结构(C或Java 实现)的接受范围和处理溢出。 Python不 支持单精度浮点数;在处理器和储蓄 内存使用,通常使用这些的原因是相形见绌 在Python中使用对象的开销,所以没有理由的复杂化 语言有两种浮点数。
- )
-
。
- 序列
-
。
。 作为一个表达式时,一片 相同类型的序列。 这意味着指数集重新编号 它从0开始。
。
序列是杰出的根据他们的可变性:
- 不变的序列
-
一个不可变的序列类型的一个对象不能改变一旦创建。 (如果 对象包含对其他对象的引用,这些其他对象 可变的,可能改变;然而,直接的对象集合 引用一个不可变对象不能改变。)
以下类型是不可变的序列:
- 字符串
-
。
- 元组
-
一个元组的物品任意Python对象。 元组的两个或两个 更多的项目是由逗号分隔的表达式列表。 一个元组 一个条目(singleton)可以由粘贴一个逗号 表达式(表达式本身并不创建一个元组, 必须使用括号表达式分组)。 一个空 元组可以由一个空对括号中。
- 字节
-
方法。
- 可变序列
-
(删除)语句。
目前有两种内在可变序列类型:
- 列表
-
是任意的Python对象列表的项目。 列表是由 把一个以逗号分隔的在方括号表达式。 (注意 没有特殊情况需要表单列表长度为0或1的。)
- 字节数组
-
构造函数。 除了可变(因此 unhashable),否则字节数组提供相同的接口和 功能不变的字节对象。
模块。
- 集类型
-
返回一组项的项数。常见 用途集快速加入测试,删除重复的序列, 和计算数学运算,如十字路口,联盟的区别, 和对称差分。
),可以包含在一个只有一个人 集。
目前有两个内在的类型:
- 集
-
。
- 冰冻的集
-
再次,它可以使用另一个集合的一个元素,或作为 一个字典键。
- 映射
-
返回的数量 项的映射。
目前一个内在映射类型:
- 字典
-
),那么他们可以交替使用索引 相同的词条。
)。
模块。
- 可调用的类型
-
)可以应用:
- 用户定义函数
-
)。 它应该被称为一个参数列表 包含相同数量的物品作为函数的形式参数 列表。
特殊属性:
属性 意义 __doc__ 如果 不可用 可写的 __name__ 函数的名字 可写的 __module__ 如果不可用。 可写的 __defaults__ 如果没有参数 有一个默认值 可写的 __code__ 代码对象代表 编译后的函数体。 可写的 __globals__ 的引用字典 包含函数的 全局变量, 全局名称空间的 模块的功能 被定义。 只读 __dict__ 名称空间支持 任意函数 属性。 可写的 __closure__ 或者一个元组的细胞 包含绑定的 函数的自由变量。 只读 __annotations__ 为 返回注释,如果 提供。 可写的 __kwdefaults__ 一个包含违约dict keyword-only参数。 可写的 大部分的属性标签“可写”检查分配的值的类型。
函数对象也支持获取和设置任意属性 可以被使用,例如,附加元数据功能。 常规属性 通过用于获取和设置这些属性。 请注意,当前 在用户自定义函数实现只支持函数属性。 功能属性内置函数可能在未来支持。
额外的信息可以从其检索函数的定义 代码对象;参见下面描述的内部类型。
- 实例方法
-
一个类对象方法结合实例,和任何一个类实例 可调用对象(通常一个用户定义的函数)。
如果不可用。
方法还支持访问任意函数(但不是设置) 底层函数对象属性。
时可以创建用户定义的方法对象的一个属性 类(也许通过该类的一个实例),如果该属性是一个 用户定义函数对象或类方法对象。
属性是原始的 函数对象。
属性。
属性的函数对象 底层的类方法。
。
是底层的函数。
当这个函数的一个属性 类。
- 发生器功能
-
异常和迭代器将已达到的集合 返回值。
- 内置函数
-
如果不可用。
- 内置的方法
-
。
- 类
- 来 初始化新实例。
- 类实例
- 类的方法。
- 模块
-
。 一个模块对象不包含代码 对象用于初始化模块(因为它不需要一旦 初始化完成)。
。
模块的名称空间是吗 字典对象。
CPython的实现细节: 因为字典CPython的清理模块,模块 字典将被清除时,模块即使超出范围 词典还住引用。 为了避免这种情况,复制字典 或保持周围的模块,而直接使用它的字典。
属性不是 礼物给C模块静态链接到解释器; 扩展模块从一个共享库,动态加载路径名 共享库文件。
- 定制类
-
(尽管有很多 钩子允许的其他方式定位属性)。 当属性 没有找到名字,搜索仍在基类的属性。 这个搜索的基类使用的C3方法解析顺序 正确的行为即使在“钻石”继承结构的存在 哪里有多重继承路径回到共同的祖先。
。
类属性赋值更新类的字典,字典 一个基类。
一个类对象可以调用(见上图)来生成一个类实例(见下文)。
是类的 如果未定义的文档字符串,或没有。
- 类实例
-
方法,叫做满足 查找。
方法,这就是所谓的而不是更新实例 直接的字典。
。
是类的实例。
- I / O对象(也称为文件对象)
-
方法 的套接字对象(或者由其他函数或方法 通过扩展模块)。
抽象类。
- 内部类型
-
内部使用的几个类型翻译暴露给用户。 他们的 定义可能会改变未来版本的翻译,但它们 这里提到的完整性。
- 代码对象
-
。 代码对象和一个函数对象的区别在于功能 对象包含函数的显式引用全局变量(模块 它定义的),而一个代码对象包含没有上下文,也默认吗 参数值是存储在函数对象,而不是在代码中对象 (因为他们代表值计算在运行时)。 不像函数 对象,代码对象是不可变的,不包含(直接或引用 间接)可变的对象。
是一个整数编码标志的翻译。
设置 如果函数是一个发电机。
在早些时候 版本的Python。
是用于内部使用。
如果未定义。
- 帧对象
-
帧对象代表执行框架。 他们可能会发生在回溯对象 (见下文)。
给出了精确的指令(这是一个索引 字节码代码的字符串对象)。
是当前框架的行号,写这个吗 从内部函数跟踪给定的线(只是最底层的 帧)。 调试器可以实现跳转命令(又名设置下一条语句) 通过编写f_lineno。
- 回溯对象
-
。
声明中没有匹配的除外 条款或条款。
- 片对象
-
函数。
如果省略了。 这些属性可以包含任意类型。
片对象支持一个方法:
- , 长度 )
- 或切片的步幅。 缺失或界外指数 处理的方式与普通片一致。
- 静态方法对象
- 构造函数。
- 类方法对象
- 构造函数。
特殊的方法名称
)。
接口在W3C文档对象模型)。
基本定制
- ] )
-
)。
用适当的参数,然后修改 在必要时创建的实例返回之前。
。
方法将不会被调用。
主要目的是允许不可变类型的子类(像什么 int、str或定制实例创建元组)。 这也是常见的 覆盖在自定义元类来创建自定义类。
- ] )
-
在运行时被提出。
- __del__ ( 自我 )
-
方法被称为对象时仍然存在 解释器退出。
请注意
价值。
警告
方法是 调用。
- __repr__ ( 自我 )
-
也用于当一个吗 “非正式”字符串表示该类的实例是必需的。
这是通常用于调试,所以重要的是表示 信息丰富而清晰。
- __str__ ( 自我 )
-
它不需要一个有效的Python 表达式:更方便或简洁的表示可以使用。 返回值必须是一个字符串对象。
- , format_spec )
-
然而,大多数类 委托格式的内置类型,或者使用一个类似的 格式化选项的语法。
标准格式语法的描述。
返回值必须是一个字符串对象。
- __lt__(self, other)
- __le__(self, other)
- __eq__(self, other)
- __ne__(self, other)
- __gt__(self, other)
- __ge__(self, other)
-
。
价值判断的结果是真或假。
对象支持 自定义比较操作,可用作为字典键。
是自己的倒影。
丰富的参数比较的方法永远不会强迫。
。
- __hash__ ( 自我 )
-
应该返回一个整数。 唯一的要求 属性对象也比较有相同的散列值,它是 建议以某种方式混合在一起(例如使用异或)的散列值 的对象的组件也参与比较的对象。
,因为 hashable集合的实现需要一个关键的散列值 不变的(如果对象的散列值的变化,它将在错误的散列 桶)。
。
)。
。
命令行选项。
- __bool__ ( 自我 )
-
,被认为是所有的实例 真实的。
自定义属性的访问
为类实例)。
- object.__getattr__(self, name)
-
例外。
方法下得到完全控制 对属性的访问。
- __getattribute__(self, name)
-
。
请注意
。
- object.__setattr__(self, name, value)
-
是分配给它的值。
。
- object.__delattr__(self, name)
- 有意义的对象。
- __dir__(self)
- 被称为对象。 必须返回列表。
实现描述符
。
- object.__get__(self, instance, owner)
- 例外。
- object.__set__(self, instance, value)
- 。
- object.__delete__(self, instance)
- 所有者的类。
调用描述符
。 如果任何 这些方法被定义为一个对象,它是一个描述符。
不包括元类。
然而,如果抬头值是一个对象定义一个描述符 方法,那么Python可能覆盖默认行为和调用描述符 方法相反。 这发生在优先级链取决于哪个 描述符方法以及它们是如何被定义的。
:
- 直接调用
- 。
- 实例绑定
- 。
- 类绑定
- 。
- 超级绑定
- 。
定义总是覆盖的重新定义 实例字典。 相反,数据描述符可以覆盖 实例。
) 作为数据描述符实现。 因此,可以定义和实例 覆盖方法。 这允许单个实例收购行为 不同于其他相同的类的实例。
功能被实现为一个数据描述符。 因此, 实例不能覆盖一个属性的行为。
__slots__
默认情况下,类的实例都有一本字典存储为属性。 这 浪费空间对象有很少的实例变量。 的空间 消费可以成为急性当创建大量的实例。
不是为每个实例创建。
- __slots__
- 为每一个实例。
使用说明 __slots__
- 定义的 子类是没有意义的。
- 声明。
- 声明。
- __slots__ ;否则,类属性将覆盖描述符 任务。
- 槽)。
- 如果一个类定义了一个槽中定义一个基类,实例变量 基类定义的位置不可访问(除了通过检索 直接从基类描述符)。 这个呈现的意义 程序定义。 在未来,检查可能被添加到防止这种情况。
- 。
- 。 映射也可以 使用;然而,在未来,特殊的意义可能分配到的值 对应于每个键。
- __class__进行 。
创建自定义类
。
。 如果其他关键字参数传递,他们 也会传递到元类。 这允许类或函数 写这显示器或改变类的创建过程:
- 修改字典之前被创建的类的类。
- 返回另一个类的一个实例——本质上执行的角色 工厂函数。
可以从这个方法调用创建一个类 不同的属性。 下面的例子添加一个新元素 字典之前创建的类:
class metacls(type):
def __new__(mcs, name, bases, dict):
dict['foo'] = 'metacls was here'
return type.__new__(mcs, name, bases, dict)
在元类允许定义方法 行为类,如不是创建一个新的实例。
属性(通常是作为一个实现 类或静态方法),之前它被称为类身体评估 类的名称和一个元组的基础参数。 它应该返回 支持的对象映射接口,将用于存储 类的命名空间。 默认是一个普通的字典。 这可能是使用, 例如,跟踪订单的类中声明的属性 返回一个有序字典。
适当的元类是由以下优先规则:
- 关键字参数传递的基地,就使用它。
- 否则,如果至少有一个基类,它使用元类。
- 使用)。
潜在的使用元类是无穷无尽的。 一些想法 探索包括日志、界面检查,自动代表团、自动 产权创造、代理、框架和自动资源 锁定/同步。
记得类成员定义的顺序:
class OrderedClass(type):
@classmethod
def __prepare__(metacls, name, bases, **kwds):
return collections.OrderedDict()
def __new__(cls, name, bases, classdict):
result = type.__new__(cls, name, bases, dict(classdict))
result.members = tuple(classdict)
return result
class A(metaclass=OrderedClass):
def one(self): pass
def two(self): pass
def three(self): pass
def four(self): pass
>>> A.members
('__module__', 'one', 'two', 'three', 'four')
。
自定义子类实例和检查
内置函数。
实现这些方法 为了允许添加抽象基类(abc)作为“虚拟基地 类”到任何类或类型(包括内置类型),包括其他 abc。
- __instancecheck__(self, instance)
- 。
- __subclasscheck__(self, subclass)
- 。
注意,这些方法都是抬头类的类型(元)。 他们 不能定义为类方法在实际的类。 这是一致的 特别的方法被称为实例的查找,只在这 情况下,类本身就是一个实例。
另请参阅
- 引入抽象基类
- 模块) 语言。
模拟可调用对象
- object.__call__(self[, args...])
-
。
模拟容器类型
;因为序列,它应该遍历值。
- object.__len__(self)
-
方法返回0 在布尔上下文被认为是错误的。
请注意
切片是专门用以下三种方法来完成的。 这样的电话
a[1:2] = b
是
a[slice(1, 2, None)] = b
。
- object.__getitem__(self, key)
-
应该提高。
请注意
将提高违法吗 索引,允许适当的检测序列的结束。
- object.__setitem__(self, key, value)
- 方法。
- object.__delitem__(self, key)
- 方法。
- object.__iter__(self)
-
。
。
- __reversed__(self)
-
内置的实现 反向迭代。 它应该返回一个迭代的新的迭代器对象 在相反的顺序容器中的所有对象。
。
)通常是 通过序列作为迭代实现。 然而,容器对象 以下特殊方法提供一个更有效的实现 也不需要的对象是一个序列。
- __contains__(self, item)
-
否则,则返回false。 映射对象,这应该考虑 键的映射而不是值或重点项目对。
。
模拟数字类型
可以定义下列方法来模拟数字对象。 方法 对应的操作由特定种类的不支持 数量(如实现。 非整型数据,逐位操作) 未定义的。
- object.__add__(self, other)
- object.__sub__(self, other)
- object.__mul__(self, other)
- object.__truediv__(self, other)
- object.__floordiv__(self, other)
- object.__mod__(self, other)
- object.__divmod__(self, other)
- object.__pow__(self, other[, modulo])
- object.__lshift__(self, other)
- object.__rshift__(self, other)
- object.__and__(self, other)
- object.__xor__(self, other)
- object.__or__(self, other)
-
功能是被支持。
。
- object.__radd__(self, other)
- object.__rsub__(self, other)
- object.__rmul__(self, other)
- object.__rtruediv__(self, other)
- object.__rfloordiv__(self, other)
- object.__rmod__(self, other)
- object.__rdivmod__(self, other)
- object.__rpow__(self, other)
- object.__rlshift__(self, other)
- object.__rrshift__(self, other)
- object.__rand__(self, other)
- object.__rxor__(self, other)
- object.__ror__(self, other)
-
。
( 强制规则会变得太复杂)。
请注意
如果右操作数的类型的子类左操作数的类型 子类提供了反映操作方法,该方法将 之前被称为左操作数的non-reflected方法。 这个动作允许 子类覆盖他们的祖先操作。
- object.__iadd__(self, other)
- object.__isub__(self, other)
- object.__imul__(self, other)
- object.__itruediv__(self, other)
- object.__ifloordiv__(self, other)
- object.__imod__(self, other)
- object.__ipow__(self, other[, modulo])
- object.__ilshift__(self, other)
- object.__irshift__(self, other)
- object.__iand__(self, other)
- object.__ixor__(self, other)
- object.__ior__(self, other)
- 。
- object.__neg__(self)
- object.__pos__(self)
- object.__abs__(self)
- object.__invert__(self)
-
)。
- object.__complex__(self)
- object.__int__(self)
- object.__float__(self)
- object.__round__(self[, n])
-
。 应该返回一个值 适当的类型。
- __index__ ( 自我 )
- 功能)。 必须返回一个整数。
与声明上下文联系
),但也可以 使用通过直接调用它们的方法。
上下文管理的典型应用包括保存和恢复各种 全局状态,锁定和释放资源,关闭打开的文件等。
。
- __enter__(self)
- 条款的声明,如果任何。
- __exit__(self, exc_type, exc_value, traceback)
-
。
如果提供的是一个例外,方法希望抑制异常 (即。 ,防止它传播),它应该返回真值。 否则,异常处理通常在退出这个方法。
方法不应该reraise传入异常; 这是调用者的责任。
特殊的方法查找
对于自定义类,隐含的调用特殊的方法是唯一的保证 正常工作如果上定义一个对象的类型,而不是对象的实例 字典。 这种行为就是下面的代码的原因提出了一个 例外:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
所实现的所有对象, 包括类型对象。 如果这些方法使用的隐式查找 传统的查找过程,调用类型对象时,他们将会失败 本身:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
错误地试图调用类的方法以这种方式不限 有时被称为“元类混乱”,并避免被绕过 实例时查找特殊方法:
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
即使对象的元类的方法:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
设置类 对象本身为了始终调用解释器)。
脚注
可能在某些情况下改变一个对象的类型,在某些 控制条件。 这通常不是一个好主意,因为它可以 导致一些非常奇怪的行为如果处理不正确。
)不支持操作失败,这就是为什么 反映方法不叫。