python 05 關於對python中引用的理解


  數據的在內存中的地址就是數據的引用。
  如果兩個變量為同一個引用,那么這兩個變量對應的數據一定相同;
  如果兩個變量對應的數據相同,引用不一定相同。
  通過id(數據)可以查看數據對應的地址,修改變量的值,其實是在修改變量的引用。
  數據可以分為:可變類型與不變類型
    可變類型:
      如果修改了數據的內容,數據的地址沒有發生改變.
      有列表,字典,set集合
    不可變類型:
      如果修改了數據的內容,數據的地址發生改變.
      有字符串,元組,數字
  當python解釋器首次啟動時,會把小數字(-5~256)和短字符串(長度小於21)緩存到緩沖區中,當在程序中使用這些數字和字符串時,就直接從緩存區中取。
    m = 300
    n = 300
    print(id(m)) # 1811121856
    print(id(n))
    不在小數字或者小字符串范圍內的數據,會在第一次使用時緩存起來
    m = 300
    n = 300
    print(id(m)) # 2345027009360
    print(id(n)) # 2345027009360

演示:
1.
變量a實際存儲的是1的引用(地址)(在程序執行過程中a被編譯為一條指令)
a = 1
b = a
print(id(a)) # 1820749280
print(id(b)) # 1820749280
a =2 # 修改不可變類型(的引用)
print(id(a)) # 1820749312 a的id已經改變
print(id(b)) # 1820749280
print(a,b)

a = [1, 2,[3,5]]
b = a
print(id(a)) # 1758314288776
print(id(b)) # 1758314288776
# a.append(3)
a[0] = 6
a[2][0] = 1
b[2][1] = 6
print(id(a)) # 1758314288776 注意a與b始終指向同一個地址
print(id(b)) # 1758314288776
print(a) # [6, 2, [1, 6]]
print(b) # [6, 2, [1, 6]]

2.

list = []
dict = {"name":"wangjie","age":23}
print(id(dict))
a = 10
list.append(dict) # 把dict的引用加入到list中 0x111 的內容是(指向){"name":"wangjie","age":23}
list.append(a) # 把a的引用加入到list中 0x222 的內容是(指向)10
print(list) # list[0] 為0x111 ,內容是(指向)數據{"name":"wangjie","age":23},list[1]的內容0x222,內容是(指向)數據10
a = 20 # 修改了a的值 a的引用發生的變化 0x333
   # 但不影響list中的引用指向的值 還是指向0x111 指向{"name":"wangjie","age":23}
   # 和0x222 指向 10
print(list)
dict["name"] = "lili" #修改了dict的值 dict為可變數據類型,dict的引用不變,但0x111的內容已經變為{'name': 'lili', 'age': 23}
print(list) # list[0]的內容是 0x111 , 指向數據{'name': 'lili', 'age': 23},list[1]的內容為0x222指向數據 10

3.
list = []
list2 = []
m = 10
def func():
  global m
  m =20
  list2 = [1,2] # 不屬於修改,修改需要通過方法,這種是覆蓋全局變量list2
  list.append(1) # 通過append 方法修改,list的引用不變
  print(list2) # [1, 2]
print(list) # []
print(m) # 10
print(id(m)) # 1811115776

func() # [1, 2]

print(list) # [1]
print(list2) # []
print(m) # 20
print(id(m)) # 1811116096

4.

def log2():
  #info_dict = {} # 存儲學生信息的字典若放在for循環外,則舊數據會被新數據覆蓋
  info_list = []
  num = input("請輸入要錄入信息的數量")
  num = int(num)
  for i in range(num):
    info_dict = {} # 重新直接對info_dict 賦值,info_dict的引用發生改變 存儲學生信息的字典要放在for循環# 內
    print("錄入第%s 位信息" % (i + 1))
    name = input("輸入姓名:")
    id = input("輸入學號")
    info_dict["姓名"] = name
    info_dict["學號"] = id
    info_list.append(info_dict)
  print(info_list)
  for info in info_list:
    for k ,v in info.items():
      print('%s = %s' % (k,v))
log2()

5.

a = [1, 2]
b = [3, 4]
a.append(b) # [1,2,[3,4]]
b.append(a)
print(a) # [1, 2, [3, 4, [...]]]
print(b) # [3, 4, [1, 2, [...]]]

6.傳遞數據,傳遞的是數據對應的地址.

a = [[]] * 5 
print(a) [[],[],[],[],[]]
print(id(a)) # 2132205131400
print(id(a[0])) # 2132205131592
print(id(a[1])) # 2132205131592
a.append(1)
print(id(a)) # 2132205131400
print(a) # [[],[],[],[],[],1]
a[0].append(2)
print(id(a[0])) # 2132205131592
print(a) # [[2],[2],[2],[2],[2],1]
a[1].append(3)
print(id(a[1])) # 2132205131592
print(a) # [[2,3],[2,3],[2,3],[2,3],[2,3],1]

7.

>>> def selfAdd(a):
    """自增"""
    a += a
>>> a_int = 1
>>> selfAdd(a_int)
>>> a_int
1
>>> a_list = [1,2]
>>> selfAdd(a_list)
>>> a_list
[1, 2, 1, 2]
總結:python中函數參數是引用傳遞(注意不是值傳遞)。對於不可變類型,因變量的值不能修改,所以運算不會影響到變量自身;而對於可變類型來說,函數體中的運算有可能
會更改傳入參數的值

8.

  += 和append()方法等對數據引用的修改一樣

9.

  a = [1,2]

  b = a * 2

  print(b)  # [1,2,1,2]

  print(id(b))  # 2745079031688

  b[0] = 55

  print(b)  # [55,2,1,2]

  print(id(b))  # 2745079031688

  print(a)  # [1,2]

  修改了b[0] ,則b[0] 的引用發生改變,但b的引用沒發生變化 

9.

  第一種情況:

  def func(x,l = []):

    for i in range(x):

      l.append(i+1)

    print(l)
  func(3)  #  [1,2,3]

  func(2)  # [1,2,3,1,2]

  第二種情況:

  def func(x,l = []):

    for i in range(x):

      l.append(i+1)

    print(l)

  list = [1,2]

  func(3,list)  # [1,2,1,2,3]

  func(2)  #  [1,2]

  函數有默認參數,定義時即為默認參數分配地址了,也只分配這一個地址,所以第一種情況,用的全是l這個列表;第二種調用func(3,list),將list變為了[1,2,1,2,3],然后調用func(2),l又指向了原先的已經定義好的空列表,所以結果為[1,2]。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM