getattr() 在 Python 中是什么及如何使用?

399 投票
15 回答
372231 浏览
提问于 2025-04-16 06:25

我看了一篇关于 getattr 函数的文章,但还是不太明白它到底是干什么用的。

我唯一明白的就是 getattr() 这个函数,比如 getattr(li, "pop") 和直接调用 li.pop 是一样的。

那我到底什么时候、怎么用这个呢?书上说它可以用来获取一个在运行时才知道名字的函数的引用,但我到底什么时候和为什么要用这个呢?

15 个回答

124

对我来说,getattr 可以这样简单地解释:

它让你可以根据字符串的内容来调用方法,而不是直接输入方法的名字。

比如,你不能这样做:

obj = MyObject()
for x in ['foo', 'bar']:
    obj.x()

因为 x 不是 builtin 类型,而是 str 类型。不过,你可以这样做:

obj = MyObject()
for x in ['foo', 'bar']:
    getattr(obj, x)()

它让你可以根据输入动态地与对象连接。我发现它在处理自定义对象和模块时特别有用。

355

在Python中,对象可以有属性,这些属性可以是数据属性,也可以是用来处理这些数据的函数(我们称之为方法)。实际上,每个对象都有一些内置的属性(你可以在Python控制台中试试 dir(None)dir(True)dir(...)dir(dir))。

举个例子,假设你有一个对象 person,它有几个属性,比如 name(名字)、gender(性别)等等。

你通常可以通过写 person.nameperson.genderperson.the_method() 来访问这些属性(无论是方法还是数据属性)。

但是,如果在写程序的时候你不知道属性的名字呢?比如你把属性的名字存储在一个叫 attr_name 的变量里。

如果

attr_name = 'gender'

那么,你就可以不写

gender = person.gender

而是写

gender = getattr(person, attr_name)

一些练习:

Python 3.4.0 (default, Apr 11 2014, 13:05:11)

>>> class Person():
...     name = 'Victor'
...     def say(self, what):
...         print(self.name, what)
... 
>>> getattr(Person, 'name')
'Victor'
>>> attr_name = 'name'
>>> person = Person()
>>> getattr(person, attr_name)
'Victor'
>>> getattr(person, 'say')('Hello')
Victor Hello

getattr 函数会在对象中找不到指定名字的属性时抛出 AttributeError 错误:

>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

不过,你可以把一个默认值作为第三个参数传入,如果这个属性不存在,就会返回这个默认值:

>>> getattr(person, 'age', 0)
0

你可以把 getattrdir 一起使用,来遍历所有属性的名字并获取它们的值:

>>> dir(1000)
['__abs__', '__add__', ..., '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

>>> obj = 1000
>>> for attr_name in dir(obj):
...     attr_value = getattr(obj, attr_name)
...     print(attr_name, attr_value, callable(attr_value))
... 
__abs__ <method-wrapper '__abs__' of int object at 0x7f4e927c2f90> True
...
bit_length <built-in method bit_length of int object at 0x7f4e927c2f90> True
...

>>> getattr(1000, 'bit_length')()
10

这在实际应用中可以用来找到所有名字以 test 开头的方法,并且 调用它们

类似于 getattr,还有一个 setattr 函数,它可以让你根据名字设置对象的属性:

>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>
238

getattr(object, 'x') object.x 是完全一样的

只有两种情况getattr才会特别有用。

  • 你不能直接写 object.x,因为你事先不知道想要哪个属性(这个属性是从字符串中来的)。这在元编程中非常有用。
  • 你想提供一个默认值。如果 object.y 不存在,会报 AttributeError 错误。但 getattr(object, 'y', 5) 会返回 5

撰写回答