对象,价值观和类型 

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__(selfother)
__le__(selfother)
__eq__(selfother)
__ne__(selfother)
__gt__(selfother)
__ge__(selfother)

价值判断的结果是真或假。

对象支持 自定义比较操作,可用作为字典键。

是自己的倒影。

丰富的参数比较的方法永远不会强迫。

__hash__ 自我 

应该返回一个整数。 唯一的要求 属性对象也比较有相同的散列值,它是 建议以某种方式混合在一起(例如使用异或)的散列值 的对象的组件也参与比较的对象。

,因为 hashable集合的实现需要一个关键的散列值 不变的(如果对象的散列值的变化,它将在错误的散列 桶)。

)。

命令行选项。

__bool__ 自我 

,被认为是所有的实例 真实的。

自定义属性的访问 

为类实例)。

object.__getattr__(selfname)

例外。

方法下得到完全控制 对属性的访问。

__getattribute__(selfname) 

请注意 

 

object.__setattr__(selfnamevalue)

是分配给它的值。

object.__delattr__(selfname)
有意义的对象。
__dir__(self) 
被称为对象。 必须返回列表。

实现描述符 

object.__get__(selfinstanceowner)
例外。
object.__set__(selfinstancevalue)
object.__delete__(selfinstance)
所有者的类。

调用描述符 

。 如果任何 这些方法被定义为一个对象,它是一个描述符。

不包括元类。

然而,如果抬头值是一个对象定义一个描述符 方法,那么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__(selfinstance) 
__subclasscheck__(selfsubclass) 

注意,这些方法都是抬头类的类型(元)。 他们 不能定义为类方法在实际的类。 这是一致的 特别的方法被称为实例的查找,只在这 情况下,类本身就是一个实例。

另请参阅 

引入抽象基类
模块) 语言。

模拟可调用对象 

object.__call__(self[, args...])

 模拟容器类型 

;因为序列,它应该遍历值。

object.__len__(self)

方法返回0 在布尔上下文被认为是错误的。

请注意 

 

切片是专门用以下三种方法来完成的。 这样的电话

a[1:2] = b

a[slice(1, 2, None)] = b

object.__getitem__(selfkey)

应该提高。

请注意 

将提高违法吗 索引,允许适当的检测序列的结束。

object.__setitem__(selfkeyvalue)
方法。
object.__delitem__(selfkey)
方法。
object.__iter__(self)

__reversed__(self) 

内置的实现 反向迭代。 它应该返回一个迭代的新的迭代器对象 在相反的顺序容器中的所有对象。

)通常是 通过序列作为迭代实现。 然而,容器对象 以下特殊方法提供一个更有效的实现 也不需要的对象是一个序列。

__contains__(selfitem)

否则,则返回false。 映射对象,这应该考虑 键的映射而不是值或重点项目对。

模拟数字类型 

可以定义下列方法来模拟数字对象。 方法 对应的操作由特定种类的不支持 数量(如实现。 非整型数据,逐位操作) 未定义的。

object.__add__(selfother)
object.__sub__(selfother)
object.__mul__(selfother)
object.__truediv__(selfother)
object.__floordiv__(selfother)
object.__mod__(selfother)
object.__divmod__(selfother)
object.__pow__(selfother[, modulo])
object.__lshift__(selfother)
object.__rshift__(selfother)
object.__and__(selfother)
object.__xor__(selfother)
object.__or__(selfother)

功能是被支持。

object.__radd__(selfother)
object.__rsub__(selfother)
object.__rmul__(selfother)
object.__rtruediv__(selfother)
object.__rfloordiv__(selfother)
object.__rmod__(selfother)
object.__rdivmod__(selfother)
object.__rpow__(selfother)
object.__rlshift__(selfother)
object.__rrshift__(selfother)
object.__rand__(selfother)
object.__rxor__(selfother)
object.__ror__(selfother)

( 强制规则会变得太复杂)。

请注意 

 

如果右操作数的类型的子类左操作数的类型 子类提供了反映操作方法,该方法将 之前被称为左操作数的non-reflected方法。 这个动作允许 子类覆盖他们的祖先操作。

object.__iadd__(selfother)
object.__isub__(selfother)
object.__imul__(selfother)
object.__itruediv__(selfother)
object.__ifloordiv__(selfother)
object.__imod__(selfother)
object.__ipow__(selfother[, modulo])
object.__ilshift__(selfother)
object.__irshift__(selfother)
object.__iand__(selfother)
object.__ixor__(selfother)
object.__ior__(selfother)
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__(selfexc_typeexc_valuetraceback) 

如果提供的是一个例外,方法希望抑制异常 (即。 ,防止它传播),它应该返回真值。 否则,异常处理通常在退出这个方法。

方法不应该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

设置类 对象本身为了始终调用解释器)。

脚注

可能在某些情况下改变一个对象的类型,在某些 控制条件。 这通常不是一个好主意,因为它可以 导致一些非常奇怪的行为如果处理不正确。

)不支持操作失败,这就是为什么 反映方法不叫。

相关文章: