變數
變數引用
在C++中,我們可能會寫下種程式碼:
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int>a={1,2,3,4,5,6};
vector<int>b;
b=a;
b[0]=0;
cout<<"a:";
for(int i:a){
cout<<i;
}
cout<<"\nb:";
for(int i:b){
cout<<i;
}
}
a:123456
b:023456
這段程式碼先宣告陣列a,然後將a複製到b,之後修改b。
輸出的結果跟想像的一樣,兩個陣列的內容相同。
但如果換成python呢?我們試試以下程式碼:
a=[1,2,3,4,5,6]
b=a
b[0]=0
print(a)
print(b)
a: [0, 2, 3, 4, 5, 6]
b: [0, 2, 3, 4, 5, 6]
這時結果就和我們想像的不一樣,在更改b時,a也被改到了。
這是執行指令b=a,意思是「將a新增別名b」,這時a和b同時指向同一個物件。
當資料型態為
- 列表 (list)
- 字典 (dict)
- 集合 (set)
時,複製變數就是在新增別名,如下:
a=[1,2,3,4,5,6]
b=a
b[0]=0
print(a)
print(b)
a: [0, 2, 3, 4, 5, 6]
b: [0, 2, 3, 4, 5, 6]
a={'x': 1, 'y': 2}
b=a
b['x']=0
print('a:',a)
print('b:',b)
a: {'x': 0, 'y': 2}
b: {'x': 0, 'y': 2}
a=[1,2,3,4,5,6]
b=a
b[0]=0
print(a)
print(b)
a: {1, 2, 3, 4}
b: {1, 2, 3, 4}
現在我們有一個結論:
執行b=a時,若a是陣列,就會指向同一個陣列
那我們看看下面的程式碼:
a = [1,2]
b = a
a[0]=0
print("a:",a)
print("b:",b)
a = [3,4]
print("a:",a)
print("b:",b)
a: [0, 2]
b: [0, 2] //受影響
a: [3, 4]
b: [0, 2] //不受影響
這段程式碼說明了如果變數重新賦值,就會指向不同內容。
可以看到以下影片,模擬程式碼運作。
基於相同概念,其實所有變數都是相同原理:執行b=a時,b與a會指向相同物件
a = 0
b = a
print(id(a)) # 顯示 a 的記憶體地址
print(id(b)) # 顯示 b 的記憶體地址
2517631631568
2517631631568
要解決複製的問題,使用.copy()
a = [1,2]
b = a
c = a.copy()
a[0]=0
print("a:",a)
print("b:",b)
print("c:",c)
a: [0, 2]
b: [0, 2] //受影響
c: [1, 2] //不受影響
交換變數名稱
在C++中若不使用函數,要交換變數會需要以下程式碼:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=1,b=2;
int tmp;
cout<<"a: "<<a<<"\n";
cout<<"b: "<<b<<"\n";
//交換
tmp=a;
a=b;
b=tmp;
cout<<"a: "<<a<<"\n";
cout<<"b: "<<b;
}
a: 1
b: 2
a: 2
b: 1
但是在python可以簡化:
a = 1
b = 2
print("a:",a)
print("b:",b)
#交換
a, b = b, a
print("-----")
print("a:",a)
print("b:",b)
a: 1
b: 2
-----
a: 2
b: 1
也可以多個同時交換:
a = 1
b = 2
c = 3
print("a:",a)
print("b:",b)
print("c:",c)
#交換
a, b, c = b, c, a
print("-----")
print("a:",a)
print("b:",b)
print("c:",c)
a: 1
b: 2
c: 3
-----
a: 2
b: 3
c: 1