HOWTO · Python

修复对象在 Python 中没有属性错误

本教程讨论对象在 Python 中没有属性错误。

本页内容

当点号前的对象无法找到所请求的属性时,Python 会引发 AttributeError。属性名可能拼写错误、定义在另一种类型上,或者对象的初始化方式与预期不同,因而没有该属性。例如,列表和 NumPy 数组是不同的类型;一种类型支持的属性不会自动出现在另一种类型上。

Python 中“对象没有某个属性”错误的含义

在 items.size 中,Python 会向绑定到 items 的对象请求名为 size 的属性。错误会指出参与访问的对象和缺失的属性名;这并不表示该名称在 Python 中的所有对象上都不可用。修改代码前,先检查接收此次属性访问的对象属于什么类型。

查找属性缺失的原因

从出错表达式所在的位置开始排查。打印或检查变量的类型,然后对照你打算使用的类或 API,核对属性名的拼写和大小写。变量也可能在更早的代码中被替换成了另一种对象,例如原本应是数组的值变成了列表。

快速检查时,dir(value) 会列出对象上许多可用的名称。它适合辅助调试,但不能证明某个属性一定无法访问:元类行为可能会提供 dir() 未列出的属性。相关内容可参阅 Python 元类指南。

下面这个小型类示例展示了接收属性访问的对象。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,并打印一条固定说明。输出文本 visitor has no name 保持英文,意思是 visitor 没有 name 属性。实例方法必须将 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。这样,其他无关的错误仍会显现。应根据程序其余部分能够安全执行的操作来选择备用值;只有当占位值对当前任务而言与缺失值含义相同时,才适合使用它。