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

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


当前回答

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)()

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

除了这里所有令人惊叹的答案之外,还有一种方法可以使用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来编写更清晰的代码。

setattr ()

我们使用setattr向类实例添加一个属性。我们传递类实例、属性名和值。

getattr ()

使用getattr可以检索这些值

例如

Employee = type("Employee", (object,), dict())

employee = Employee()

# Set salary to 1000
setattr(employee,"salary", 1000 )

# Get the Salary
value = getattr(employee, "salary")

print(value)

它也从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)

年龄: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'))

性别:男性

AttributeError: 'Person'对象没有属性'sex'

下面是一个快速而简单的示例,演示了一个类如何根据使用getattr()执行的操作系统来触发save方法的不同版本。

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

现在让我们在一个例子中使用这个类:

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()