日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python class 是否存在某个变量_一文抵十课,考验你的Python变量是否理解透彻了

發布時間:2025/3/21 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python class 是否存在某个变量_一文抵十课,考验你的Python变量是否理解透彻了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

變量是編程的基礎概念,Python 的變量也看似很簡單,但是如果理解不當,生搬硬套,可能會遇到一些麻煩。

下面用 10 個代碼示例展示 Python 的 變量 本質。

快來看看你對 Python 的變量理解是否到位了。文章無廢話。小白感覺理解有壓力的可以看視頻,手把手用 Thonny 逐步講解。

10個例子,使用 Thonny 解剖式講解,刷新你對 Python 變量的認知 | Python 進階_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com

1. 只是個名字

當 a 出現在賦值語句的左側時,它僅僅代表一個 名字:

a = 1024 a = 'davycloud' a = ['點贊', '關注', '收藏']

賦值完成后,這個名字和右側的對象就 綁定 在一起了。在這個過程中,

  • a 是否已經綁定了其它對象完全不用考慮,也就是說,不管前面 a 綁定了什么,或者什么也沒有綁定,它都是個名字。
  • 只要名字是合法的,它可以綁定到任意的對象,完全不用考慮對象的類型

2. 對象的引用

綁定了對象的名字,也就是我們常說的 變量,當它出現在賦值語句的右側時,它代表了 對象的引用:

a = [] b = a

當把 a 賦給 b 的時候,a 代表的是列表對象的引用,也就是說:

  • 列表對象本體不受影響
  • 并不會復制出一個新的列表
  • a 和 b 在這之后都是這同一個列表的引用

因為列表是可變對象,所以可以通過 a 和 b 任意一個變量改變對象,兩者同時都會反映出對象的變化:

a.append(1) # a = [1], b = [1] b.append(2) # a = [1, 2], b = [1, 2]“ 可變對象下面會再次討論

3. 先右 后左

把多個賦值語句連在一起時,處理的順序是從右往左:

a = b = []

這里 b 首先是充當名字,綁定到一個列表對象;然后又充當對象的引用,賦給另一個名字 a,也就是說,上面的語句等價于:

# 寫法1 b = [] a = b

它和下面的賦值方式有著截然不同的后果:

# 寫法2 b = [] a = []

在這里,兩個變量分別綁定了兩個不同的列表,它們之間互相并無關聯。

但是這里有個有趣的地方,如果我們把 [] 換成一個整數 1 或者字符串,那么 寫法 1 和 寫法 2 兩種賦值方式在結果上就并無不同。

4. 變化取決于對象

繼續上面的例子,兩個名字綁定到同一個列表,操作其中一個,另一個就受到影響:

b = [] a = b a.append(1)

這是因為列表是一個 可變對象。而如果把列表換成數字或者字符串:

b = 'davy' a = b a += 'cloud'

對 a 的自增操作并不會影響到 b。先給出自增操作的等價形式:

a = a + 'cloud'

可見,這仍然是一次賦值而已。利用前面的結論:

  • 右邊的 a 代表對象的引用,即 'davy',它和 'cloud' 加起來生成一個新的對象
  • 左邊的 a 是一個名字,它再次和新對象,即 'davycloud' 綁定在一起

也就是說,這中間總共產生了 3 個字符串對象。

我們仔細觀察不難看出,當我們想要 改變對象的時候,必須通過的是對象提供的接口(對于列表來說,就是 append 方法,或者下標操作,對于其它對象,可以是改變它的屬性),而 不可能通過重新賦值改變對象 。

賦值只是名字的綁定,再次強調。

這里我們還能得到另外一個結論:

不可變對象被多次引用/綁定不會產生副作用。比如說:

# a, b 綁定到同一個對象 a = b = 'davy'# a, b 分別綁定到一個對象 a = 'davy' b = 'davy'

在上面的示例中,兩種綁定的語法含義是不同的,但是,因為字符串是不可變的,也就是說,即使 a 和 b 綁定到同一個字符串,它們也不會互相影響。既然這樣,那么又何必在內存中重復創建兩個一模一樣的的 davy 字符串出來呢。不如直接復用好了,可以節省一點內存:

>>> a = 'davy' >>> b = 'davy' >>> a is b True

再次但是,這種優化并不是全局的,也就是說,并不是只要是相同的字符串就一定是唯一的對象:

>>> a += 'cloud' >>> b += 'cloud' >>> a is b False >>> a 'davycloud' >>> b 'davycloud' >>> a == b True

所以呢,大家知道有這種情況就好,對于不可變對象都要使用 == 去比較,而不要用 is,因為它可能會產生時而正確時而錯誤的詭異結果。

5. 瞬間交換的秘密

當一個賦值語句中右側出現了多個對象,或者多個對象的引用,它們會自動打包成一個元組。

在賦值語句的左邊,需要有相同數量的名字供解包:

a = [1024] b = 'davycloud' a, b = b, a

這個例子中,綜合利用前 3 個規則:

  • 先右后左
  • 變量是對象的引用
  • 左側是名字

不難得出一個結論,這里兩個名字交換了對象的引用,對象本體并沒有移動。

6. 都是名字的錯

a 沒有賦值,直接地運行結果:

>>> print(a) Traceback (most recent call last):File "<stdin>", line 1, in <module> NameError: name 'a' is not defined

這里看似很好解釋,變量 a 沒有定義嘛!加一行賦值語句不就行了。

但是:

  • 這里報的錯誤是 NameError: name 'a' is not defined,名字未定義錯誤,并不是變量未定義
  • 仔細想想,這個 a 到底是什么呢?數字?字符串?函數?類?模塊?

7. 我們都是變量

接上一個例子:

a = 1def a():passclass a():passimport sys as a

不僅是賦值,定義函數,定義類,導入模塊或模塊中的對象,都是在綁定名字。

定義函數是把一個名字綁定到一個函數對象,定義類是把名字綁定到一個類對象,導入一個模塊就是把一個名字綁定到一個模塊對象。

Python 中一切皆對象,所以,它們都是變量。

8. 傳參也不過是命名

既然說到了函數,那就繼續來看函數的傳參:

def func(x):return x

這個函數毫無用處,但是正好用來解釋參數的傳入和傳出。

a = func(1024) b = func(a)

函數中的參數 x 其實也是一個名字,只是它的 作用域 是限定在 func 函數的內部。

給函數傳參就如同是賦值,給這個內部名字綁定一個對象,而出參就好似出現在賦值右側的變量,就是傳出來一個對象引用:

# 偽代碼 func(1024):x = 1024 a = x“ 關于變量的作用域這里點到為止,有機會再詳細討論。

注意,上面的規則對所有的對象類型都是一樣的,無論是可變對象還是不可變對象。

根據前面的分析,很容易得出結論:

  • 如果參數/返回是不可變對象,那么它是不會產生副作用的
  • 如果參數/返回是可變對象,那么函數內部對它的操作都會影響其它綁定到這個對象上的變量

因此,對于可變對象的傳參需要格外謹慎。特別地,函數的默認參數不要使用可變對象。

因為默認參數的綁定是在函數定義階段發生的:

def get_people(people=[]):return people

在調用 get_people 時,除非給 people 指定一個參數,否則它綁定的總是在函數定義時刻產生的那個列表。而我們的本意可能是,如果默認沒有參數,就生成一個空列表。

一個常規的做法是,在函數內部新建對象:

def get_people(people=None):if people is None:people = []return people

9. 刪不掉的對象

Python 提供了 del 關鍵字可以用來 刪除 變量,然而實際上這個操作的后果只是把變量名字和對象解綁,然后刪掉這個名字。刪掉的名字如果再訪問,會觸發 NameError,就好像它從來沒存在過一樣。

而對象呢,它們只是減少了一個引用:

a = [1, 2, 3] b = a del a # 完全不會影響到 b

一個對象有多個變量引用到的情況下不會被清理很好理解,其實即使當前沒有任何名字綁定到這個對象,這個對象也不會立即刪除掉:

>>> a = [] >>> id(a) 2292904305736>>> del a >>> a Traceback (most recent call last):File "<stdin>", line 1, in <module> NameError: name 'a' is not defined >>> b = [] >>> id(b) 2292904305736

總而言之,del 的含義就是 解綁,別指望它刪除對象。

“ 對象的引用計數和銷毀是 Python 內部維護的,一般情況下我們無需關心。有興趣的可以查閱 Python 的垃圾回收相關內容。

10. 淺拷貝?零拷貝!

終極例子:

a = [[]] * 3 a[0].append(1) print(a) # [[1], [1], [1]]

這里迷惑性比較強,因為用到了列表的 * 操作。當對一個列表乘法操作時,一般的理解是對其中的元素進行 復制(copy)。

看到 copy 很容易又會提起所謂的 淺拷貝 和 深拷貝,這里顯然不是深拷貝,那么想當然的很容易理解為是淺拷貝,錯!

這里不過又是一次隱形的賦值,讓我們把它展開:

x = [] y = [x] a = [x, x, x] # a = y * 3 的等價寫法 a[0].append(1) print(a)

最重要的就是第 3 行代碼:

  • y * 3 是要把 y 中的元素復制 3 份
  • 現在這個元素就是 x,
  • 那么就讓 x 重復出現 3 次吧
  • 實際的效果就是 [x, x, x],

x 是對象的引用,所以我們只是把對象的引用復制了 3 份,對象本體完全沒有觸及。

那么如果要真正復制這個列表應該怎么做呢?利用到系統提供的淺拷貝函數,或者是利用 切片:

# 列表內置的 copy 方法 a = [x.copy() for i in range(3)]# 利用切片 a = [x[:] for i in range(3)]# 利用 copy 標準庫 from copy import copy a = [copy(x) for i in range(3)]

前面兩種方法是列表對象自帶的接口,而 copy 模塊則更加通用。

小結

  • 變量指的是名字綁定了對象
  • 綁定時,變量就是名字
  • 使用時,變量代表對象的引用
  • 變量改變的只有綁定關系
  • 想要改變/復制對象,需要看對象有沒有提供方法

除了以上內容,關于變量還有個重要的概念就是理解它的 作用域,這部分內容將另撰文講解。


如果本文對你有幫助,請 點贊、分享、關注,謝謝!

總結

以上是生活随笔為你收集整理的python class 是否存在某个变量_一文抵十课,考验你的Python变量是否理解透彻了的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。