与变量名相关联的任何内容都必须在程序的内存中存储。一个简单的想法是,每个字节的内存都有一个索引号。为了简单起见,让我们想象一个简单的计算机,这些索引号从0(第一个字节)开始,向上增加到所有字节的数量。
因此,在地址12000处是一个,在12001处是一个,12002处是一个 ... 最后一个
位于12037处。
我强调这一点,因为它对每种编程语言都是根本的。12000是该字符串的“地址”。它也是它位置的“引用”。对于大多数意图和目的,地址是指针是引用。不同的语言对这些有所不同,但本质上它们是相同的 - 处理给定编号的数据块。
Python和Java尽可能地隐藏了这种寻址,而像C这样的语言很乐意暴露指针的真实面貌。
从中学到的,对象引用是存储在内存中的数据位置的数字。(指针也是如此。)
现在,大多数编程语言区分简单类型:字符和数字,以及复杂类型:字符串、列表和其他复合类型。这就是对象引用的区别所在。
因此,在执行简单类型操作时,它们是独立的,它们各自具有其自己的存储器。想象一下Python中的以下序列:
>>> a = 3
>>> b = a
>>> b
3
>>> b = 4
>>> b
4
>>> a
3
变量 a
和 b
并不共享存储它们值的内存。但对于复杂类型:
>>> s = [ 1, 2, 3 ]
>>> t = s
>>> t
[1, 2, 3]
>>> t[1] = 8
>>> t
[1, 8, 3]
>>> s
[1, 8, 3]
我们将变量t
赋值为s
,但是很明显在这种情况下,t
就是s
——它们共享相同的内存。等等,什么!我们发现s
和t
都是指向同一个对象的引用 - 它们只是简单地共享(指向)内存中的相同地址。
Python与其他编程语言的一个不同之处在于,它将字符串视为一种简单类型,这些字符串是独立的,因此它们的行为类似于数字:
>>> j = 'Pussycat'
>>> k = j
>>> k
'Pussycat'
>>> k = 'Owl'
>>> j
'Pussycat' # <
在C
中,字符串被处理为复杂类型,并且会像Python列表示例一样运行。
所有通过引用处理的对象被修改时,所有对该对象的引用都能"看到"这个变化。因此,如果将对象传递给修改它的函数(即:更改包含数据的内存内容),那么这个变化也会反映在该函数之外。
但是,如果简单类型被更改或传递给函数,则会被复制到函数中,因此在原始函数中看不到变化。
例如:
def fnA( my_list ):
my_list.append( 'A' )
a_list = [ 'B' ]
fnA( a_list )
print( str( a_list ) )
['B', 'A']
但是:
def fnB( number ):
number += 1
x = 3
fnB( x )
print( x )
3
记住,被引用使用的“对象”的内存是所有副本共享的,而简单类型的内存则不是,因此这两种类型的操作方式明显不同。
a = 1234
的情况下,a
是对对象1234
的一个引用,并且这个引用对象的行为被称为“对象引用”。 - vcyf56rtrfca
就是 对象的一个引用。 - timgeb