HOWTO · Python

修復物件在 Python 中沒有屬性錯誤

本教程討論物件在 Python 中沒有屬性錯誤。

本頁內容

當點號前的物件無法完成屬性查找時,Python 會引發 AttributeError。要求的名稱可能拼錯、定義在另一種型別上,或因物件的初始化方式與預期不同而不存在。例如,list 和 NumPy 陣列是不同型別,因此某個屬性可用於其中一種型別,不代表另一種也能使用。

Python 的「object has no attribute」錯誤代表什麼

在 items.size 中,Python 會向綁定至 items 的物件查找名為 size 的屬性。錯誤訊息會指出該物件和缺少的名稱;這不代表該名稱在 Python 中任何地方都無法使用。修改程式碼前,先確認接收這次屬性存取的物件型別。

找出缺少屬性的原因

從發生錯誤的運算式開始檢查。列印或查看變數的型別,再對照原本打算使用的類別或 API,確認拼字與大小寫是否正確。變數也可能先前被換成另一種物件,例如原本應是陣列,卻變成了 list。

若要快速檢查,dir(value) 會列出物件上許多可用的名稱。它適合用來輔助除錯,但不能完整證明某個屬性無法存取:metaclass 的行為可能會提供 dir() 沒有列出的屬性。更多相關資訊請參閱 Python metaclass 指南。

以下的小型類別範例能清楚說明接收屬性存取的物件。User 定義了 name,而無關的 Guest 類別則沒有:

class User:
    def __init__(self, name):
        self.name = name


class Guest:
    pass


person = User("Ada")
visitor = Guest()
print(person.name)
print(type(visitor).__name__)
try:
    visitor.name
except AttributeError:
    print("visitor has no name")

第一次存取會成功,因為 person 是具有 name 的 User。最後一次存取則是向 Guest 實例 visitor 查找 name;範圍限定的例外處理程式會捕捉該次查找引發的 AttributeError,並印出清楚的說明。定義在實例上的方法,第一個參數必須包含 self,Python 才能在呼叫方法時傳入該實例。

修正屬性錯誤

請依原因選擇修正方式:更正拼字錯誤、改在預期的物件上存取屬性,或在應提供該屬性的類別中定義並初始化屬性或方法。不要只為了取得某個名稱就更改物件型別;其他程式碼可能依賴原本的型別,並在型別變更後出錯。

若要正常存取屬性,請讓類別與物件資料保持一致:

執行以下範例。程式碼區塊及其輸出會依原樣保留;其中若有英文標籤,仍會是英文,並未翻譯:

class Account:
    def __init__(self, owner):
        self.owner = owner


account = Account("Mina")
print(account.owner)
Mina

安全處理可選屬性

如果某個屬性確實是可選的,hasattr(value, "name") 會檢查屬性查找是否成功。當有無此屬性時需要採取不同處理方式,可以先用它作為條件。若要提供備用值,getattr(value, "name", default) 會在該次查找引發 AttributeError 時回傳預設值。setattr() 的用途是指定屬性;它不會在查找時提供備用值。

如果直接處理錯誤更清楚,就只把可能失敗的屬性存取放進 try 區塊,並在其中捕捉 AttributeError。這樣能讓其他無關的錯誤繼續顯現。請根據程式其餘部分能安全處理的情況選擇備用值;只有當佔位值對你的任務而言與缺少值代表相同意思時,才適合使用它。