我最近读了关于getattr()函数的文章。问题是我仍然不能理解它的用法。我对getattr()的唯一理解是,getattr(li,“pop”)与调用li.pop相同。

我不理解书中提到如何使用它来获取函数的引用,而直到运行时才知道它的名称。也许这就是我在编程方面的新手。谁能解释一下这个问题?我何时以及如何使用它?


当前回答

对我来说,getattr是最简单的解释方式:

它允许您根据字符串的内容调用方法,而不是键入方法名称。

例如,你不能这样做:

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

因为x不是内置类型,而是str。然而,你可以这样做:

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

它允许您根据输入动态地连接对象。我发现它在处理自定义对象和模块时很有用。

其他回答

getattr的一个非常常见的用例是将数据映射到函数。

例如,在Django或Pylons这样的web框架中,getattr可以直接将web请求的URL映射到将要处理它的函数。例如,如果你看一下Pylons的路由,你会发现(至少在默认情况下)它分割了一个请求的URL,比如:

http://www.example.com/customers/list

分为“客户”和“列表”。然后它搜索名为CustomerController的控制器类。假设它找到该类,它创建该类的实例,然后使用getattr获取其list方法。然后调用该方法,将请求作为参数传递给它。

一旦你掌握了这个思想,扩展web应用程序的功能就变得非常容易:只需向控制器类添加新的方法,然后在页面中创建链接,为这些方法使用适当的url。所有这些都是由getattr实现的。

除了这里所有令人惊叹的答案之外,还有一种方法可以使用getattr来节省大量代码行并保持舒适。这种想法源于代码的可怕表示,有时可能是必要的。

场景

假设你的目录结构如下:

- superheroes.py
- properties.py

你可以在superheroes。py中获得关于雷神,钢铁侠,奇异博士的信息。你很聪明地在一个紧凑字典的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'],
}

现在,假设您希望在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']

...以及更多基于键和超级英雄返回不同值的函数。

在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']

你大大减少了代码行数、函数和重复!

哦,当然,如果你的变量有像properties_of_thor这样的坏名字,它们可以通过简单的操作来创建和访问

def get_superhero_weapon(hero):
    superhero = 'properties_of_{}'.format(hero)
    all_properties = getattr(properties, superhero)
    return all_properties['weapon']

注意:对于这个特殊的问题,可以有更聪明的方法来处理这种情况,但是我们的想法是在正确的地方使用getattr来编写更清晰的代码。

我认为这个例子是不言自明的。它运行第一个参数的方法,其名称在第二个参数中给出。

class MyClass:
   def __init__(self):
      pass
   def MyMethod(self):
      print("Method ran")

# Create an object
object = MyClass()
# Get all the methods of a class
method_list = [func for func in dir(MyClass) if callable(getattr(MyClass, func))]
# You can use any of the methods in method_list
# "MyMethod" is the one we want to use right now

# This is the same as running "object.MyMethod()"
getattr(object,'MyMethod')()

Getattr (object, 'x')完全等价于object.x。

getattr只在两种情况下有用。

你不能写object。X,因为您事先不知道您想要哪个属性(它来自字符串)。对于元编程非常有用。 您需要提供一个默认值。对象。如果没有y, y将引发AttributeError。但是getattr(object, 'y', 5)将返回5。

对我来说,getattr是最简单的解释方式:

它允许您根据字符串的内容调用方法,而不是键入方法名称。

例如,你不能这样做:

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

因为x不是内置类型,而是str。然而,你可以这样做:

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

它允许您根据输入动态地连接对象。我发现它在处理自定义对象和模块时很有用。