如何理解 Python 中“一切皆对象”?
本文最近更新于 2018 年 07 月 05 日
Python 是一门优雅而健壮的编程语言,它继承了传统编译语言的强大性和通用性,同时也借鉴了简单脚本和解释语言的易用性。
Python 编程简明教程 https://jsntn.com/python
在 Python 中有一句话——一切皆对象。那应该如何理解“一切皆对象”?
何为对象?
不同的编程语言以不同的方式定义“对象”。某些语言中,它意味着所有对象必须有属性和方法;另一些语言中,它意味着所有的对象都可以子类化。在 Python 中,定义是松散的,某些对象既没有属性也没有方法,而且不是所有的对象都可以子类化。但是 Python 的万物皆对象从感性上可以解释为:Python 中的一切都可以赋值给变量或者作为参数传递给函数。1
在 The Python Language Reference2 中更是具体指出3:每个对象都有标识(ID),类型和值组成。对象一旦建立,它的 ID 就不会改变;我们可以把它理解为该对象在内存中的地址。is
操作符比较两个对象的 ID;id()
函数返回一个表示对象 ID 的整数。对象的类型决定对象能够支持的操作(例如,它是否具有长度?),还定义该类型的对象可能有的值/取值范围。type()
函数返回对象的类型(它本身也是一个对象)。与 ID 一样,对象的类型也是不可以修改的。4
解释
“一切皆对象”也就是说在 Python 中下列语句其实都有一个共同点:
i = 1
s = "abc"
def foo(): pass
class C(object): pass
instance = C()
l = [1, 2, 3]
t = (1, 2, 3)
它们在 Python 解释器中执行的时候,都会在堆中新建了一个对象,然后把新建的对象绑定到变量名上:
i = 1 #新建一个 PyIntObject 对象,绑定到 i 上
s = "abc" #新建一个 PyStringObject 对象,绑定到 s 上
def foo(): pass #新建一个 PyFunctionObject 对象,绑定到 foo 上
class C(object): pass #新建一个类对象,绑定到 C 上
instance = C() #新建一个实例对象,绑定到 instance 上
l = [1, 2, 3] #新建一个 PyListObject 对象,绑定到 l 上
t = (1, 2, 3) #新建一个 PyTupleObject 对象,绑定到 t 上
分析
每个对象都有一个唯一的身份标识自己,可以使用内建函数 id()
来得到,我们可以把这个值理解为该对象的内存地址:
>>> i = 1
>>> id(i)
8104016
>>>
对象的类型决定了对象可以用来保存什么类型的值,有哪些属性和方法,可以进行哪些操作,遵循怎样的规则。可以使用内建函数 type()
来查看对象的类型(代码续上):
>>> type(i)
<type 'int'>
>>> type(type)
<type 'type'> #type 也是一种特殊的对象 type
>>> i
1
>>>
“身份标识(ID)”、“类型”和“值”随对象被创建而产生。如果对象支持更新操作,则它的值是可变的,否则为只读(数字、字符串、元组等均不可变)。只要对象还存在,这三个特性就一直存在。
所以,简单来看,i = 1
是将变量 i
和数字 3 进行连接,使 i
成为对象 3 的一个引用(可以理解为变量是到对象的内存空间的一个指针),需要注意的是:变量总是连接到对象,而不会连接到其他变量。
从概念上可以这样理解:对象是堆上分配的一个内存空间,用来表示对象所代表的值;变量是一个系统创建的元素,拥有指向对象的引用(引用是从变量到对象的指针)。
举例,当我们定义如下函数时:
>>> def hi(name = "Jason"):
return "Hi! " + name
>>> print hi()
Hi! Jason
我们可以将函数赋值给一个变量(我们这里不使用小括号,因为我们并不准备调用 hi
函数):
>>> hello = hi
>>> hi()
'Hi! Jason'
>>> hello()
'Hi! Jason'
>>> hi
<function hi at 0x02AA3770>
>>> type(hi)
<type 'function'>
>>> type(hello)
<type 'function'>
>>> id(hi)
44709744
>>> id(hello)
44709744
>>> #hi 和 hello 属于同一类型,指向了同一个对象
调用 hi
函数:
>>> hello = hi()
>>> type(hello)
<type 'str'>
>>> id(hello)
44730208
>>> #hello 对象的类型和标识被更改
如果我们删掉 hi
函数:
>>> hello
'Hi! Jason'
>>> hi()
'Hi! Jason'
>>> del hi
>>> hi
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
hi
NameError: name 'hi' is not defined
>>> hello
'Hi! Jason'
>>>
hi
函数不再存在,hello
变量指向的对象不受影响。
扩展阅读:
- 译自《Dive into Python》,原文链接 [return]
- 本文参考 Python 3.5.5 documentation 的 Language Reference,链接地址为 docs.python.org/3.5/reference/ [return]
- 原文链接 docs.python.org/3.5/reference/datamodel.html#objects-values-and-types [return]
- 在某些情况下,在某些可控的条件下,是可以更改对象的类型的。但它一般不是好主意,因为如果它处理不正确,可能导致一些非常奇怪的行为。 [return]
最近更新: