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

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


当前回答

我在Python2.7.17中尝试过

有些人已经回答了。不过我已经试过打电话了 getattr(obj, 'set_value'),这没有执行set_value方法,所以我改为getattr(obj, 'set_value')()——>这有助于调用相同的。

示例代码:

示例1:

    class GETATT_VERIFY():
       name = "siva"
       def __init__(self):
           print "Ok"
       def set_value(self):
           self.value = "myself"
           print "oooh"
    obj = GETATT_VERIFY()
    print getattr(GETATT_VERIFY, 'name')
    getattr(obj, 'set_value')()
    print obj.value

其他回答

Python中的对象可以具有属性——数据属性和使用这些属性的函数(方法)。实际上,每个对象都有内置属性(在Python控制台中尝试dir(None), dir(True), dir(…),dir(dir))。

例如,你有一个对象人,它有几个属性:名字,性别等。

访问这些属性(无论是方法还是数据对象)通常需要写:person.name, person。性别、person.the_method()等。

但是,如果在编写程序时不知道属性的名称怎么办?例如,您将属性名存储在名为attr_name的变量中。

if

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

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

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)

当我从存储在类中的数据创建XML文件时,如果属性不存在或类型为None,我经常会收到错误。在本例中,我的问题不是不知道属性名是什么,而是存储在该属性中的数据。

class Pet:
    def __init__(self):
        self.hair = None
        self.color = None

如果我使用hasattr来执行此操作,即使属性值为None类型,它也会返回True,这将导致我的ElementTree set命令失败。

hasattr(temp, 'hair')
>>True

如果属性值的类型为None, getattr也会返回它,这将导致我的ElementTree set命令失败。

c = getattr(temp, 'hair')
type(c)
>> NoneType

我现在使用以下方法来处理这些情况:

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

这是我使用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来编写更清晰的代码。