最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中訪問類變量與實(shí)例變量的完整步驟

 更新時間:2025年10月31日 09:39:21   作者:2401_89134191  
在Python中,類變量和實(shí)例變量的訪問方式有所不同,理解它們的區(qū)別和正確訪問方法很重要,所以本文給大家詳細(xì)介紹了Python訪問類變量與實(shí)例變量的完整步驟,需要的朋友可以參考下

好的,我們來系統(tǒng)地拆解一下 Python 中訪問類變量和實(shí)例變量的完整步驟。這是一個非常核心且容易混淆的概念。

我會遵循以下結(jié)構(gòu),由淺入深,確保你徹底理解:

  1. 核心定義:明確什么是類變量和實(shí)例變量。
  2. 查找規(guī)則:詳細(xì)解釋 Python 在訪問屬性時遵循的 “查找鏈”(Lookup Chain)。
  3. 代碼演練:通過實(shí)例代碼,一步步追蹤查找過程。
  4. 修改與遮蔽:解釋如何修改變量,以及 “遮蔽”(Shadowing)現(xiàn)象。
  5. 可變對象陷阱:探討當(dāng)類變量是可變對象(如列表、字典)時的特殊情況。
  6. 總結(jié)與速查表:提供一個清晰的總結(jié),幫助你快速決策。

1. 核心定義

類變量 (Class Variable)

  • 定義位置:在類的內(nèi)部,但在任何方法的外部。
  • 所屬對象:屬于類本身。
  • 共享性:被所有該類的實(shí)例(對象)共享。一個實(shí)例對類變量的修改(在特定條件下)會影響所有其他實(shí)例。
  • 作用:通常用于定義所有實(shí)例都共有的屬性或常量,比如物種(species)、默認(rèn)計數(shù)等。

實(shí)例變量 (Instance Variable)

  • 定義位置:通常在類的 __init__ 方法中,以 self. 開頭。
  • 所屬對象:屬于單個實(shí)例。
  • 唯一性:每個實(shí)例都有自己獨(dú)立的一份拷貝。修改一個實(shí)例的實(shí)例變量不會影響其他實(shí)例。
  • 作用:用于存儲每個實(shí)例獨(dú)有的數(shù)據(jù),比如名字(name)、年齡(age)等。

代碼示例:

class Dog:
    # 類變量:所有狗都共享這個屬性
    species = "Canis lupus familiaris"
    count = 0 # 用于計數(shù)狗的數(shù)量
 
    def __init__(self, name, age):
        # 實(shí)例變量:每個狗對象都有自己的 name 和 age
        self.name = name
        self.age = age
        Dog.count += 1 # 每次創(chuàng)建實(shí)例,類變量 count 加 1

2. 查找規(guī)則:屬性查找鏈 (Attribute Lookup Chain)

當(dāng)你使用 instance.attribute 的形式訪問一個屬性時,Python 會嚴(yán)格按照以下順序進(jìn)行查找,直到找到為止:

查找實(shí)例自身的命名空間

  • Python 首先會檢查該實(shí)例對象是否擁有這個屬性。你可以通過 instance.__dict__ 查看實(shí)例的屬性字典。
  • 如果在 __dict__ 中找到了 attribute,就直接返回它的值。查找結(jié)束。

查找類的命名空間

  • 如果實(shí)例自身沒有這個屬性,Python 會接著檢查該實(shí)例所屬的類是否擁有這個屬性。你可以通過 Class.__dict__ 查看類的屬性字典。
  • 如果在 __dict__ 中找到了 attribute,就返回它的值。查找結(jié)束。

查找父類的命名空間(繼承鏈)

  • 如果類自身也沒有,Python 會沿著繼承鏈向上,依次查找所有父類和祖先類的 __dict__。
  • 這個過程遵循 Method Resolution Order (MRO),即方法解析順序。

拋出異常

  • 如果沿著整個繼承鏈都找不到這個屬性,Python 會拋出 AttributeError 異常。

一句話總結(jié): 先找實(shí)例,再找類,最后找父類。 (instance -> Class -> Parent Class)

3. 代碼演練:追蹤查找過程

讓我們創(chuàng)建一個實(shí)例,并追蹤訪問不同變量時的路徑。

# 沿用上面的 Dog 類
dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)

場景 1:訪問實(shí)例變量 dog1.name

  1. 查找 dog1 的 __dict__{'name': 'Buddy', 'age': 3}。
  2. 找到了 name,值為 'Buddy'。
  3. 查找停止,返回 'Buddy'。

場景 2:訪問類變量 dog1.species

  1. 查找 dog1 的 __dict__{'name': 'Buddy', 'age': 3}
  2. 沒有找到 species。
  3. 繼續(xù)查找 dog1 所屬的類 Dog 的 __dict__。
  4. 在 Dog.__dict__ 中找到了 species,值為 "Canis lupus familiaris"。
  5. 查找停止,返回 "Canis lupus familiaris"。

場景 3:訪問類變量 Dog.count

  1. 這里直接從類 Dog 開始查找。
  2. 在 Dog.__dict__ 中找到了 count,值為 2。
  3. 查找停止,返回 2。

場景 4:訪問一個不存在的變量 dog1.weight

  1. 查找 dog1 的 __dict__{'name': 'Buddy', 'age': 3}。
  2. 沒有找到 weight
  3. 繼續(xù)查找 Dog 的 __dict__。
  4. 也沒有找到 weight。
  5. Dog 沒有父類(除了 object),在 object 中也找不到。
  6. 查找失敗,拋出 AttributeError: 'Dog' object has no attribute 'weight'。

4. 修改與遮蔽 (Shadowing)

修改變量的行為取決于你通過什么來修改它。

4.1 修改實(shí)例變量

這是最常見的操作,直接在實(shí)例的 __dict__ 中創(chuàng)建或更新屬性。

dog1.age = 4 # 修改 dog1 自己的 age
print(dog1.age)  # 輸出: 4
print(dog2.age)  # 輸出: 5 (不受影響)

4.2 修改類變量

這里有兩種方式,效果完全不同:

方式一:通過類名修改(推薦)

這會真正地修改類的 __dict__ 中的值,所有實(shí)例都會受到影響。

Dog.species = "Canis familiaris" # 通過類名修改
 
print(Dog.species)  # 輸出: Canis familiaris
print(dog1.species) # 輸出: Canis familiaris (dog1 會查找到更新后的類變量)
print(dog2.species) # 輸出: Canis familiaris (dog2 也會查找到更新后的類變量)

方式二:通過實(shí)例修改(導(dǎo)致遮蔽)

不會修改類變量,而是會在該實(shí)例自己的 __dict__ 中創(chuàng)建一個同名的實(shí)例變量。

這個新創(chuàng)建的實(shí)例變量會 “遮蔽”(shadow)掉類變量,也就是說,之后再通過這個實(shí)例訪問該變量時,會直接返回實(shí)例自己的那個,而不再去查找類。

# 此時,Dog.species 是 "Canis familiaris"
print(f"Before shadowing, dog1.__dict__: {dog1.__dict__}") # {'name': 'Buddy', 'age': 4}
 
dog1.species = "Wolf" # 通過實(shí)例修改,觸發(fā)遮蔽
 
print(f"After shadowing, dog1.__dict__: {dog1.__dict__}") # {'name': 'Buddy', 'age': 4, 'species': 'Wolf'}
print(f"Dog.__dict__['species']: {Dog.__dict__['species']}") # 'Canis familiaris' (類變量沒變!)
 
print(dog1.species) # 輸出: Wolf (訪問的是實(shí)例自己的 species)
print(dog2.species) # 輸出: Canis familiaris (dog2 沒有被遮蔽,訪問的仍是類變量)
print(Dog.species)  # 輸出: Canis familiaris (類變量本身沒變)

5. 可變對象陷阱 (Mutable Object Pitfall)

這是一個非常經(jīng)典的面試題和錯誤來源。當(dāng)類變量是可變對象(如列表 list、字典 dict、集合 set)時,通過實(shí)例對其進(jìn)行原地修改(in-place modification),會影響所有實(shí)例。

原因:因為實(shí)例和類共享同一個可變對象的引用。

代碼示例:

class Cat:
    # 類變量,一個空列表
    tricks = []
 
    def __init__(self, name):
        self.name = name
 
cat1 = Cat("Kitty")
cat2 = Cat("Lucy")
 
# 通過實(shí)例 cat1 向 tricks 列表添加元素
cat1.tricks.append("play dead")
 
# 查看結(jié)果
print(cat1.tricks) # 輸出: ['play dead']
print(cat2.tricks) # 輸出: ['play dead'] (Oh no! cat2 的 tricks 也變了)
print(Cat.tricks)  # 輸出: ['play dead'] (實(shí)際上是類變量被修改了)
 
# 檢查它們是否指向同一個對象
print(id(cat1.tricks)) # e.g., 140183245326144
print(id(cat2.tricks)) # e.g., 140183245326144 (和上面的 id 相同)
print(id(Cat.tricks))  # e.g., 140183245326144 (和上面的 id 相同)

陷阱分析:cat1.tricks.append(...) 這個操作,Python 首先在 cat1.__dict__ 中找 tricks,沒找到,然后去 Cat.__dict__ 中找到了 tricks 列表。接著,它對這個找到的列表對象本身執(zhí)行了 append 操作。因為所有實(shí)例和類都指向這同一個列表對象,所以大家都看到了變化。

如何避免?如果你想讓每個實(shí)例都有自己獨(dú)立的可變對象(比如一個空列表),你應(yīng)該在 __init__ 方法中初始化它。

class Cat:
    def __init__(self, name):
        self.name = name
        # 在實(shí)例化時,為每個實(shí)例創(chuàng)建一個獨(dú)立的列表
        self.tricks = []
 
cat1 = Cat("Kitty")
cat2 = Cat("Lucy")
 
cat1.tricks.append("play dead")
 
print(cat1.tricks) # 輸出: ['play dead']
print(cat2.tricks) # 輸出: [] (cat2 的列表不受影響)

6. 總結(jié)與速查表

特性類變量 (Class Variable)實(shí)例變量 (Instance Variable)
定義位置類內(nèi)部,方法外部通常在 __init__ 方法中,以 self. 開頭
所屬對象實(shí)例
共享性被所有實(shí)例共享每個實(shí)例獨(dú)有
訪問方式Class.var 或 instance.varinstance.var
查找順序實(shí)例查找失敗后,再查找類優(yōu)先查找實(shí)例
修改方式Class.var = new_value (影響所有實(shí)例)instance.var = new_value (只影響當(dāng)前實(shí)例)
通過實(shí)例修改instance.var = new_value 會創(chuàng)建一個同名的實(shí)例變量,遮蔽類變量直接修改實(shí)例自己的變量
可變對象風(fēng)險如果是可變對象(如列表),通過實(shí)例進(jìn)行原地修改(append等)會影響所有實(shí)例每個實(shí)例的可變對象都是獨(dú)立的,無此風(fēng)險

實(shí)踐建議:

  1. 明確意圖:如果一個屬性對所有實(shí)例都通用,用類變量。如果每個實(shí)例都需要自己獨(dú)立的一份,用實(shí)例變量。
  2. 修改類變量用類名:為了代碼清晰,避免歧義,修改類變量時始終使用 Class.variable 的形式。
  3. 警惕可變類變量:除非你明確希望所有實(shí)例共享一個可變對象(例如,一個全局計數(shù)器),否則不要將可變對象用作類變量來存儲實(shí)例相關(guān)的狀態(tài)。

希望這個全面的拆解能幫助你徹底掌握類變量和實(shí)例變量的訪問機(jī)制!

以上就是Python中訪問類變量與實(shí)例變量的完整步驟的詳細(xì)內(nèi)容,更多關(guān)于Python訪問類變量與實(shí)例變量的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • python實(shí)現(xiàn)KNN分類算法

    python實(shí)現(xiàn)KNN分類算法

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)KNN分類算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Python正則表達(dá)式以及常用匹配實(shí)例

    Python正則表達(dá)式以及常用匹配實(shí)例

    在處理字符串時,經(jīng)常會遇到查找符合某些復(fù)雜規(guī)則字符串的需求,正則表達(dá)式就是用于描述這些規(guī)則的工具,下面這篇文章主要給大家介紹了關(guān)于Python正則表達(dá)式以及常用匹配的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • python pygame實(shí)現(xiàn)擋板彈球游戲

    python pygame實(shí)現(xiàn)擋板彈球游戲

    這篇文章主要為大家詳細(xì)介紹了python pygame實(shí)現(xiàn)擋板彈球游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Numpy中的mask的使用

    Numpy中的mask的使用

    這篇文章主要介紹了Numpy中的mask的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • 用tensorflow搭建CNN的方法

    用tensorflow搭建CNN的方法

    本篇文章主要介紹了用tensorflow搭建CNN的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Python邊緣檢測之prewitt,sobel和laplace算子詳解

    Python邊緣檢測之prewitt,sobel和laplace算子詳解

    這篇文章主要為大家詳細(xì)介紹了Python邊緣檢測中prewitt、sobel和laplace算子的使用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-04-04
  • Python+Turtle實(shí)現(xiàn)繪制勾股樹

    Python+Turtle實(shí)現(xiàn)繪制勾股樹

    畢達(dá)哥拉斯樹,也叫“勾股樹”,是由畢達(dá)哥拉斯根據(jù)勾股定理所畫出來的一個可以無限重復(fù)的樹形圖形。本文將利用Python中的Turtle庫實(shí)現(xiàn)勾股樹的繪制,感興趣的可以了解一下
    2023-01-01
  • 用pickle存儲Python的原生對象方法

    用pickle存儲Python的原生對象方法

    下面小編就為大家?guī)硪黄胮ickle存儲Python的原生對象方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Python使用matplotlib繪制三維圖形示例

    Python使用matplotlib繪制三維圖形示例

    這篇文章主要介紹了Python使用matplotlib繪制三維圖形,結(jié)合實(shí)例形式分析了Python基于matplotlib庫繪制三維圖形的相關(guān)操作技巧與注意事項,需要的朋友可以參考下
    2018-08-08
  • 利用python-docx模塊寫批量生日邀請函

    利用python-docx模塊寫批量生日邀請函

    這篇文章主要為大家詳細(xì)介紹了利用python-docx模塊批量生日邀請函,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08

最新評論

思南县| 承德市| 巫山县| 大石桥市| 清流县| 通渭县| 梅河口市| 晋宁县| 卢龙县| 藁城市| 浙江省| 双鸭山市| 仁怀市| 惠州市| 昭通市| 罗江县| 泾阳县| 德阳市| 商水县| 浮梁县| 仪征市| 昔阳县| 阜城县| 巴青县| 隆昌县| 建湖县| 读书| 定结县| 丰顺县| 闸北区| 蒲城县| 临颍县| 衡水市| 灵川县| 临泉县| 永平县| 内乡县| 沙湾县| 马山县| 博客| 青岛市|