回答你的询问:“那为什么a=100;b=a;a=101
不会改变 b 的值”,我提醒你,即使在 C 中,情况也不会如此。事实是a
and b
是指针,并且相等,并不意味着更改为a
影响b
。他们不是别名。*a
and *b
可能是,但不是a
and b
.
在 C 语言中,常量字符串非常相似。
char *a="hello";
char *b=a;
a="foo";
printf("%s\n", b);
// prints hello
是的,a和b是指针。但它仍然是a
当你打字时你会改变a="foo";
,而不是其内容。所以,是的,a
and b
我们是平等的……直到,你说a="foo";
当他们不再相等时,因为你改变了a。它们只是指针。毕竟这是一个类似于另一个的值。看到这一点并不陌生a
and b
在此代码中不再等于它应在的代码中
int a=12;
int b=a;
a=15;
他们本来是平等的,后来却不平等了。指针只是值。地址。
可以共享的正是该地址中的内容。这并不奇怪。
int T[10]={1,2,3,4,5,6,7,8,9,10};
int *a=&(T[2]);
int *b=a;
printf("%d %d\n", *a, *b);
// prints 3 3
*a=5;
printf("%d %d\n", *a, *b);
// prints 5 5
您可能想知道为什么我需要整个数组。好吧,这只是为了向您展示指针的这种“别名”行为只不过是这个看似不那么神奇的例子
int T[10]={1,2,3,4,5,6,7,8,9,10};
int ia=2;
int ib=a;
printf("%d %d\n", T[ia], T[ia]);
// prints 3 3
T[ia]=5;
printf("%d %d\n", T[ia], T[ib]);
// prints 5 5
指针就是这样。指数。除了它们是所有内存的全局大数组中的索引形式之外。但“别名”并没有什么神奇之处*a
and *b
,事实上这种“别名”行为影响*a
and *b
, 但不是a
and b
(改变a不会改变b)。只要ia
and ib
在我的最后一个示例中没有改变并且保持相等,之间存在别名T[ia]
and T[ib]
(显然,你会说,他们都是T[2]
。嗯,是的,“显然”,但只不过是指针),并且之间没有“别名”ia
and ib
; ia=5
,不会影响价值T[ib]
。再说一次,是的,“显然”,但并不比改变更明显a
不改变 的值*b
.
现在,回到Python:是的,变量包含指向对象的指针,而不是对象本身。但是,如果你改变 a,你就会改变指针。
a=[1,2,3,4]
b=a
print(a[1],b[1]) # prints 2 2
a[1]=5
print(a[1],b[1]) # prints 5 5
之间存在“别名”a[?]
and b[?]
因为我们说过b=a
. But
a=[1,2,3,4]
b=a
a=[0,2,3,4]
print(a[0], b[0]) # prints 0 1
a 和 b 之间没有“别名”
但是,你可能会问,那么,我怎样才能改变 a 的内容,而不改变a
本身(指针)。
好吧,我们刚刚做到了。没有*
python 中的运算符(嗯,有一个,字面意思是*
,但这与此事无关)。因此,如果a
and b
是一个内容可以修改的对象(就像我们刚才所做的列表。或者字典。或者类的实例。或者库提供的一些特定对象,例如 ndarray 或 pandas dataframes),只要a=b
,并且你不改变的值a
and b
,当您更改其中之一的内容时(a[1]=12
or a['bla']='foo'
or a.foo=15
,或者...)它影响另一个的内容(显然:它们是同一个对象)
但并非所有对象都是可修改的。
a=12
b=a
# The is no `a.value=15` that would change a values, without changing the object
这些是不可变的对象。为什么我在 C 中使用常量字符串类比
char *a="hello";
char *b=a;
a="foo"; // Doesn't change b
因为,同样,它们也可能是对象。但您无法更改其内容。你不能strcpy(a,"bar")
,因为它们是常量字符串。所以,如果你想改变a
您必须更改指针,而不是内容。
对于不可变对象也是一样的
a=12
b=a
# Only way to change a value is to change a
a=13
所以,从字面上看12
不是一个值,而是一个指向实例的指针int
(这是一个思维模型,而不是现实)。当然a
不知何故是一个指针。但唯一的说法是a
不再“指向”其值为的 int12
,但现在指向一个 int,其值为13
,并不是要改变所指向的内容a
,因为它是不可变的,但要改变a
,并使其“指向”另一个对象,其值为13
同样(对于习惯几乎所有其他语言的人来说更令人惊讶)
a="hello"
b=a
a[0]='H' # wouldn't work
行不通。字符串是不可变的。获得资本 H 的唯一方法是
a="hello"
b=a
a="Hello"
但当然,这并不影响b
.
元组也是如此:a=(1,2); b=a
你不能a[0]=3
, 你必须a=(3,2)
这不影响b
因此,您可以将所有变量视为指针。但没有&
and *
操作员。没有显式引用、取消引用运算符。只是,如果a=b
、 和 是可变的,那么 a 的内容与 b 的内容相同,即使您更改a
的内容(通过说a[...]=...
例如)。而如果a=b
但都是不可变的,那么,内容a
与内容相同b
,但这并不重要,因为你无法更改的内容a
, only a
本身,通过说a=...