getattr() 在 Python 中是什么及如何使用?
我看了一篇关于 getattr
函数的文章,但还是不太明白它到底是干什么用的。
我唯一明白的就是 getattr()
这个函数,比如 getattr(li, "pop")
和直接调用 li.pop
是一样的。
那我到底什么时候、怎么用这个呢?书上说它可以用来获取一个在运行时才知道名字的函数的引用,但我到底什么时候和为什么要用这个呢?
15 个回答
对我来说,getattr
可以这样简单地解释:
它让你可以根据字符串的内容来调用方法,而不是直接输入方法的名字。
比如,你不能这样做:
obj = MyObject()
for x in ['foo', 'bar']:
obj.x()
因为 x 不是 builtin
类型,而是 str
类型。不过,你可以这样做:
obj = MyObject()
for x in ['foo', 'bar']:
getattr(obj, x)()
它让你可以根据输入动态地与对象连接。我发现它在处理自定义对象和模块时特别有用。
在Python中,对象可以有属性,这些属性可以是数据属性,也可以是用来处理这些数据的函数(我们称之为方法)。实际上,每个对象都有一些内置的属性(你可以在Python控制台中试试 dir(None)
、dir(True)
、dir(...)
和 dir(dir)
)。
举个例子,假设你有一个对象 person
,它有几个属性,比如 name
(名字)、gender
(性别)等等。
你通常可以通过写 person.name
、person.gender
或 person.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
你可以把 getattr
和 dir
一起使用,来遍历所有属性的名字并获取它们的值:
>>> 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'
>>>
getattr(object, 'x')
和 object.x
是完全一样的。
只有两种情况,getattr
才会特别有用。
- 你不能直接写
object.x
,因为你事先不知道想要哪个属性(这个属性是从字符串中来的)。这在元编程中非常有用。 - 你想提供一个默认值。如果
object.y
不存在,会报AttributeError
错误。但getattr(object, 'y', 5)
会返回5
。