Python getattr() 究竟是什么以及如何使用它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4075190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is getattr() exactly and how do I use it?
提问by Terence Ponce
I've recently read about the getattr()function. The problem is that I still can't grasp the idea of its usage. The only thing I understand about getattr()is that getattr(li, "pop")is the same as calling li.pop.
我最近阅读了有关该getattr()功能的信息。问题是我仍然无法理解它的用法。我唯一理解的getattr()是这getattr(li, "pop")与调用li.pop.
I didn't understand when the book mentioned how you use it to get a reference to a function without knowing its name until run-time. Maybe this is me being a noob in programming, in general. Could anyone shed some light on the subject? When and how do I use this exactly?
我不明白这本书何时提到如何使用它来获取对函数的引用,而直到运行时才知道其名称。总的来说,这可能是我在编程方面的菜鸟。任何人都可以对这个主题有所了解吗?我何时以及如何使用它?
采纳答案by blue_note
getattr(object, 'x')is completely equivalentto object.x.
getattr(object, 'x')完全等价于object.x.
There are only two caseswhere getattrcan be useful.
有只有两种情况,其中getattr可能是有用的。
- you can't write
object.x, because you don't know in advance which attribute you want (it comes from a string). Very useful for meta-programming. - you want to provide a default value.
object.ywill raise anAttributeErrorif there's noy. Butgetattr(object, 'y', 5)will return5.
- 你不能写
object.x,因为你事先不知道你想要哪个属性(它来自一个字符串)。对于元编程非常有用。 - 你想提供一个默认值。如果没有,
object.y将提出一个。但会回来。AttributeErrorygetattr(object, 'y', 5)5
回答by Josh
Here's a quick and dirty example of how a class could fire different versions of a save method depending on which operating system it's being executed on using getattr().
这是一个快速而肮脏的示例,说明一个类如何根据正在使用的操作系统来触发不同版本的 save 方法getattr()。
import os
class Log(object):
def __init__(self):
self.os = os.name
def __getattr__(self, name):
""" look for a 'save' attribute, or just
return whatever attribute was specified """
if name == 'save':
try:
# try to dynamically return a save
# method appropriate for the user's system
return getattr(self, self.os)
except:
# bail and try to return
# a default save method
return getattr(self, '_save')
else:
return getattr(self, name)
# each of these methods could have save logic specific to
# the system on which the script is executed
def posix(self): print 'saving on a posix machine'
def nt(self): print 'saving on an nt machine'
def os2(self): print 'saving on an os2 machine'
def ce(self): print 'saving on a ce machine'
def java(self): print 'saving on a java machine'
def riscos(self): print 'saving on a riscos machine'
def _save(self): print 'saving on an unknown operating system'
def which_os(self): print os.name
Now let's use this class in an example:
现在让我们在一个例子中使用这个类:
logger = Log()
# Now you can do one of two things:
save_func = logger.save
# and execute it, or pass it along
# somewhere else as 1st class:
save_func()
# or you can just call it directly:
logger.save()
# other attributes will hit the else
# statement and still work as expected
logger.which_os()
回答by Robert Rossney
A pretty common use case for getattris mapping data to functions.
一个非常常见的用例getattr是将数据映射到函数。
For instance, in a web framework like Django or Pylons, getattrmakes it straightforward to map a web request's URL to the function that's going to handle it. If you look under the hood of Pylons's routing, for instance, you'll see that (by default, at least) it chops up a request's URL, like:
例如,在像 Django 或 Pylons 这样的 Web 框架中,getattr可以直接将 Web 请求的 URL 映射到将要处理它的函数。例如,如果您深入了解 Pylons 的路由,您会看到(至少在默认情况下)它分割了请求的 URL,例如:
http://www.example.com/customers/list
into "customers" and "list". Then it searches for a controller class named CustomerController. Assuming it finds the class, it creates an instance of the class and then uses getattrto get its listmethod. It then calls that method, passing it the request as an argument.
分为“客户”和“列表”。然后它搜索名为 的控制器类CustomerController。假设它找到了类,它会创建类的一个实例,然后使用它getattr来获取它的list方法。然后调用该方法,将请求作为参数传递给它。
Once you grasp this idea, it becomes really easy to extend the functionality of a web application: just add new methods to the controller classes, and then create links in your pages that use the appropriate URLs for those methods. All of this is made possible by getattr.
一旦掌握了这个想法,扩展 Web 应用程序的功能就变得非常容易:只需向控制器类添加新方法,然后在页面中创建链接,使用这些方法的适当 URL。所有这一切都是由getattr.
回答by warvariuc
Objects in Python can have attributes -- data attributes and functions to work with those (methods). Actually, every object has built-in attributes.
Python 中的对象可以具有属性——数据属性和使用这些(方法)的函数。实际上,每个对象都有内置属性。
For example you have an object person, that has several attributes: name, gender, etc.
例如你有一个对象person,一个具有多个属性:name,gender,等。
You access these attributes (be it methods or data objects) usually writing: person.name, person.gender, person.the_method(), etc.
您可以访问这些属性(无论是方法或数据对象),通常写作:person.name,person.gender,person.the_method()等。
But what if you don't know the attribute's name at the time you write the program? For example you have attribute's name stored in a variable called attr_name.
但是如果您在编写程序时不知道属性的名称怎么办?例如,您将属性名称存储在名为attr_name.
if
如果
attr_name = 'gender'
then, instead of writing
然后,而不是写
gender = person.gender
you can write
你可以写
gender = getattr(person, attr_name)
Some practice:
一些实践:
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
getattrwill raise AttributeErrorif attribute with the given name does not exist in the object:
getattrAttributeError如果对象中不存在具有给定名称的属性,则将引发:
>>> getattr(person, 'age')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'
But you can pass a default value as the third argument, which will be returned if such attribute does not exist:
但是你可以传递一个默认值作为第三个参数,如果这样的属性不存在,它将被返回:
>>> getattr(person, 'age', 0)
0
You can use getattralong with dirto iterate over all attribute names and get their values:
您可以使用getattrwithdir迭代所有属性名称并获取它们的值:
>>> 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
A practical use for this would be to find all methods whose names start with testand call them.
对此的实际用途是查找名称以 开头test并调用它们的所有方法。
Similar to getattrthere is setattrwhich allows you to set an attribute of an object having its name:
类似于getattr那里,setattr它允许您设置具有其名称的对象的属性:
>>> setattr(person, 'name', 'Andrew')
>>> person.name # accessing instance attribute
'Andrew'
>>> Person.name # accessing class attribute
'Victor'
>>>
回答by NuclearPeon
For me, getattris easiest to explain this way:
对我来说,getattr这样解释最简单:
It allows you to call methods based on the contents of a string instead of typing the method name.
它允许您根据字符串的内容而不是键入方法名称来调用方法。
For example, you cannot do this:
例如,您不能这样做:
obj = MyObject()
for x in ['foo', 'bar']:
obj.x()
because x is not of the type builtin, but str. However, you CAN do this:
因为 x 不是类型builtin,而是str。但是,您可以这样做:
obj = MyObject()
for x in ['foo', 'bar']:
getattr(obj, x)()
It allows you to dynamically connect with objects based on your input. I've found it useful when dealing with custom objects and modules.
它允许您根据输入动态连接对象。我发现它在处理自定义对象和模块时很有用。
回答by Kduyehj
# getattr
class hithere():
def french(self):
print 'bonjour'
def english(self):
print 'hello'
def german(self):
print 'hallo'
def czech(self):
print 'ahoj'
def noidea(self):
print 'unknown language'
def dispatch(language):
try:
getattr(hithere(),language)()
except:
getattr(hithere(),'noidea')()
# note, do better error handling than this
dispatch('french')
dispatch('english')
dispatch('german')
dispatch('czech')
dispatch('spanish')
回答by Evgeni Sergeev
I sometimes use getattr(..)to lazily initialise attributes of secondary importance just before they are used in the code.
我有时getattr(..)习惯于在代码中使用次要属性之前懒惰地初始化它们。
Compare the following:
比较以下内容:
class Graph(object):
def __init__(self):
self.n_calls_to_plot = 0
#...
#A lot of code here
#...
def plot(self):
self.n_calls_to_plot += 1
To this:
对此:
class Graph(object):
def plot(self):
self.n_calls_to_plot = 1 + getattr(self, "n_calls_to_plot", 0)
The advantage of the second way is that n_calls_to_plotonly appears around the place in the code where it is used. This is good for readability, because (1) you can immediately see what value it starts with when reading how it's used, (2) it doesn't introduce a distraction into the __init__(..)method, which ideally should be about the conceptual state of the class, rather than some utility counter that is only used by one of the function's methods for technical reasons, such as optimisation, and has nothing to do with the meaning of the object.
第二种方式的优点是n_calls_to_plot只出现在代码中使用它的地方周围。这有利于可读性,因为 (1) 在阅读它的使用方式时,您可以立即看到它的开头是什么值,(2) 它不会干扰__init__(..)方法,理想情况下应该是关于类的概念状态,而不是一些效用计数器,出于技术原因(例如优化)仅由函数的方法之一使用,并且与对象的含义无关。
回答by btathalon
Quite frequently when I am creating an XML file from data stored in a class I would frequently receive errors if the attribute didn't exist or was of type None. In this case, my issue wasn't not knowing what the attribute name was, as stated in your question, but rather was data ever stored in that attribute.
当我从存储在类中的数据创建 XML 文件时,如果属性不存在或类型为 ,我会经常收到错误None。在这种情况下,我的问题不是不知道属性名称是什么,如您的问题所述,而是数据是否曾经存储在该属性中。
class Pet:
def __init__(self):
self.hair = None
self.color = None
If I used hasattrto do this, it would return Trueeven if the attribute value was of type Noneand this would cause my ElementTree setcommand to fail.
如果我hasattr以前这样做,True即使属性值是类型,它也会返回None,这会导致我的 ElementTreeset命令失败。
hasattr(temp, 'hair')
>>True
If the attribute value was of type None, getattrwould also return it which would cause my ElementTree setcommand to fail.
如果属性值是 type None,getattr也会返回它,这会导致我的 ElementTreeset命令失败。
c = getattr(temp, 'hair')
type(c)
>> NoneType
I use the following method to take care of these cases now:
我现在使用以下方法来处理这些情况:
def getRealAttr(class_obj, class_attr, default = ''):
temp = getattr(class_obj, class_attr, default)
if temp is None:
temp = default
elif type(temp) != str:
temp = str(temp)
return temp
This is when and how I use getattr.
这是我何时以及如何使用getattr.
回答by Jules Damji
Another use of getattr() in implementing a switch statement in Python. It uses both reflection to get the case type.
getattr() 在 Python 中实现 switch 语句的另一个用途。它使用两种反射来获取案例类型。
import sys
class SwitchStatement(object):
""" a class to implement switch statement and a way to show how to use gettattr in Pythion"""
def case_1(self):
return "value for case_1"
def case_2(self):
return "value for case_2"
def case_3(self):
return "value for case_3"
def case_4(self):
return "value for case_4"
def case_value(self, case_type=1):
"""This is the main dispatchmethod, that uses gettattr"""
case_method = 'case_' + str(case_type)
# fetch the relevant method name
# Get the method from 'self'. Default to a lambda.
method = getattr(self, case_method, lambda: "Invalid case type")
# Call the method as we return it
return method()
def main(_):
switch = SwitchStatement()
print swtich.case_value(_)
if __name__ == '__main__':
main(int(sys.argv[1]))
回答by unixia
Other than all the amazing answers here, there is a way to use getattrto save copious lines of code and keeping it snug. This thought came following the dreadful representation of code that sometimes might be a necessity.
除了这里所有令人惊奇的答案之外,还有一种方法可以getattr用来保存大量代码行并使其保持舒适。这个想法是在可怕的代码表示之后出现的,有时可能是必需的。
Scenario
设想
Suppose your directory structure is as follows:
假设你的目录结构如下:
- superheroes.py
- properties.py
And, you have functions for getting information about Thor, Iron Man, Doctor Strangein superheroes.py. You very smartly write down the properties of all of them in properties.pyin a compact dictand then access them.
并且,您有获取有关Thor, Iron Man, Doctor Strangein 的信息的函数superheroes.py。您非常巧妙地将所有这些属性的属性写properties.py在一个压缩文件中dict,然后访问它们。
properties.py
properties.py
thor = {
'about': 'Asgardian god of thunder',
'weapon': 'Mjolnir',
'powers': ['invulnerability', 'keen senses', 'vortex breath'], # and many more
}
iron_man = {
'about': 'A wealthy American business magnate, playboy, and ingenious scientist',
'weapon': 'Armor',
'powers': ['intellect', 'armor suit', 'interface with wireless connections', 'money'],
}
doctor_strange = {
'about': ' primary protector of Earth against magical and mystical threats',
'weapon': 'Magic',
'powers': ['magic', 'intellect', 'martial arts'],
}
Now, let's say you want to return capabilities of each of them on demand in superheroes.py. So, there are functions like
现在,假设您想在superheroes.py. 所以,有这样的功能
from .properties import thor, iron_man, doctor_strange
def get_thor_weapon():
return thor['weapon']
def get_iron_man_bio():
return iron_man['about']
def get_thor_powers():
return thor['powers']
...and more functions returning different values based on the keys and superhero.
...以及更多基于键和超级英雄返回不同值的函数。
With the help of getattr, you could do something like:
在 的帮助下getattr,您可以执行以下操作:
from . import properties
def get_superhero_weapon(hero):
superhero = getattr(properties, hero)
return superhero['weapon']
def get_superhero_powers(hero):
superhero = getattr(properties, hero)
return superhero['powers']
You considerably reduced the number of lines of code, functions and repetition!
您大大减少了代码、函数和重复的行数!
Oh and of course, if you have bad names like properties_of_thorfor variables , they can be made and accessed by simply doing
哦,当然,如果你有像properties_of_thorfor variables这样的坏名字,它们可以通过简单的方式来创建和访问
def get_superhero_weapon(hero):
superhero = 'properties_of_{}'.format(hero)
all_properties = getattr(properties, superhero)
return all_properties['weapon']
NOTE: For this particular problem, there can be smarter ways to deal with the situation, but the idea is to give an insight about using getattrin right places to write cleaner code.
注意:对于这个特定的问题,可以有更聪明的方法来处理这种情况,但我们的想法是提供有关getattr在正确的地方使用以编写更清晰的代码的见解。
回答by Barny
It is also clarifying from https://www.programiz.com/python-programming/methods/built-in/getattr
它还从https://www.programiz.com/python-programming/methods/built-in/getattr澄清
class Person:
age = 23
name = "Adam"
person = Person()
print('The age is:', getattr(person, "age"))
print('The age is:', person.age)
The age is: 23
年龄:23
The age is: 23
年龄:23
class Person:
age = 23
name = "Adam"
person = Person()
# when default value is provided
print('The sex is:', getattr(person, 'sex', 'Male'))
# when no default value is provided
print('The sex is:', getattr(person, 'sex'))
The sex is: Male
性别是:男
AttributeError: 'Person' object has no attribute 'sex'
AttributeError: 'Person' 对象没有属性 'sex'

