你不会找到像 C++11 那样严格的定义,因为 Python 没有像 C++11 这样的正式规范,它有一个 reference manual 像 pre-ISO C++ 一样。 Data model 章节非常严谨:
对象是 Python 对数据的抽象。 Python 程序中的所有数据都由对象或对象之间的关系表示。 (在某种意义上,按照冯诺依曼的“存储程序计算机”模型,代码也由对象表示。)
每个对象都有一个标识、一个类型和一个值。对象的身份一旦创建就永远不会改变;您可能会将其视为对象在内存中的地址。 …
glossary 也有一个更短的定义:
任何具有状态(属性或值)和定义行为(方法)的数据。
确实,Python 中的所有东西都有方法和(其他)属性。即使没有公共方法,也有一组从object 基类继承的特殊方法和值,例如__str__ 方法。
在 2.2 之前的 Python 版本中并非如此,这也是我们为几乎相同的事物(对象、数据、值)使用多个词的部分原因; type, class... 但是从那时起,以下几种事物是相同的:
- 对象。
- 函数可以返回或产生的东西。
- 可以存储在变量(包括参数)中的东西。
-
object 类型实例的事物(通常是间接地,通过一两个子类)。
- 可以是表达式产生的值。
- CPython 中由指向
PyObject 结构的指针表示的事物。
……等等。
这就是“一切都是对象”的意思。
这也意味着Python没有像Java那样的“原生类型”和“类类型”,或者像C#那样的“值类型”和“引用类型”;只有一种东西,对象。
这句话让我相信任何种类的所有标记也被认为是对象,包括运算符、标点符号、空格等。真的是这样吗?
没有。这些东西没有价值,所以它们不是对象。1
另外,变量不是对象。与 C 风格的变量不同,Python 变量不是具有包含值的类型的内存位置,它们只是绑定到某个命名空间中的值的名称。2 这就是为什么您不能传递引用的原因变量;没有“东西”可以参考。3
分配目标也不是对象。它们有时看起来很像值,甚至核心开发人员有时也会将 a, b = 1, 2 中的 a, b 松散地称为元组对象,但那里没有元组。4
对于numpy.array(或array.array 或ctypes.Structure)的元素,还有一些明显的模糊性。当您编写a[0] = 3 时,3 对象不会像使用list 那样存储在array 中。相反,numpy 存储了一些 Python 甚至不理解的字节,但它可以用来在数组范围的操作中执行“与 3 相同的事情”,或者制作 3 对象的新副本,如果你稍后请求a[0] = 3。
但是如果你回到定义,很明显这个“虚拟3”不是一个对象——虽然它有类型和值,但它没有标识。
1。在元级别,您可以编写一个导入钩子,它可以将导入的代码作为字节字符串、解码的 Unicode 字符串、令牌元组列表、AST 节点、代码对象或模块进行操作,所有这些都是对象……但在“正常”级别,在导入的代码中,令牌等不是对象。
2。在幕后,几乎总是有一个字符串对象来表示该名称,存储在表示命名空间的字典或元组中,如您通过调用globals() 或dir(self) 所见。但这不是变量是的。
3。闭包单元是一种表示对变量的引用的方式,但实际上,单元本身就是一个对象,不同范围内的变量只是该单元的一种稍微特殊的名称。
4.然而,在a[0] = 3 中,虽然a[0] 不是一个值,但a 和0 是,因为这个赋值等价于表达式a.__setitem__(0, 3),只是它不是一个表达式。