¿Qué es y cómo utilizar getattr() en Python?

Resuelto Terence Ponce asked hace 13 años • 15 respuestas

Leí un artículo sobre la getattrfunción, pero todavía no entiendo para qué sirve.

Lo único que entiendo getattr()es que getattr(li, "pop")es lo mismo que llamar li.pop.

¿Cuándo y cómo uso esto exactamente? El libro dice algo sobre su uso para obtener una referencia a una función cuyo nombre no se conoce hasta el tiempo de ejecución, pero ¿cuándo y por qué debería usarlo?

Terence Ponce avatar Nov 02 '10 12:11 Terence Ponce
Aceptado

Los objetos en Python pueden tener atributos: atributos de datos y funciones para trabajar con esos (métodos). En realidad, cada objeto tiene atributos integrados (pruebe dir(None),,, en dir(True)la consola de Python).dir(...)dir(dir)

Por ejemplo, tienes un objeto personque tiene varios atributos: name, gender, etc.

Accede a estos atributos (ya sean métodos u objetos de datos) generalmente escribiendo: person.name, person.gender, person.the_method(), etc.

Pero ¿qué pasa si no sabes el nombre del atributo en el momento de escribir el programa? Por ejemplo, tiene el nombre del atributo almacenado en una variable llamada attr_name.

si

attr_name = 'gender'

entonces, en lugar de escribir

gender = person.gender

puedes escribir

gender = getattr(person, attr_name)

Algunas prácticas:

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

getattrse generará AttributeErrorsi el atributo con el nombre de pila no existe en el objeto:

>>> getattr(person, 'age')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'

Pero puedes pasar un valor predeterminado como tercer argumento, que será devuelto si dicho atributo no existe:

>>> getattr(person, 'age', 0)
0

Puede utilizar getattrjunto con dirpara iterar sobre todos los nombres de atributos y obtener sus valores:

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

Un uso práctico para esto sería encontrar todos los métodos cuyos nombres comiencen con testy llamarlos .

Similar a getattrlo setattrque le permite establecer un atributo de un objeto que tiene su nombre:

>>> setattr(person, 'name', 'Andrew')
>>> person.name  # accessing instance attribute
'Andrew'
>>> Person.name  # accessing class attribute
'Victor'
>>>
warvariuc avatar Nov 02 '2010 08:11 warvariuc

getattr(object, 'x') es completamente equivalente a object.x.

Sólo hay dos casos en los que getattrpuede resultar útil.

  • no puedes escribir object.xporque no sabes de antemano qué atributo quieres (proviene de una cadena). Muy útil para metaprogramación.
  • desea proporcionar un valor predeterminado. object.ygenerará un AttributeErrorsi no hay y. Pero getattr(object, 'y', 5)regresará 5.
blue_note avatar Apr 10 '2019 09:04 blue_note

Para mí, getattres más fácil explicarlo de esta manera:

Le permite llamar a métodos según el contenido de una cadena en lugar de escribir el nombre del método.

Por ejemplo, no puedes hacer esto:

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

porque x no es del tipo builtin, pero str. Sin embargo, PUEDES hacer esto:

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

Le permite conectarse dinámicamente con objetos según su entrada. Lo he encontrado útil cuando trato con objetos y módulos personalizados.

NuclearPeon avatar Aug 30 '2013 17:08 NuclearPeon

Un caso de uso bastante común getattres asignar datos a funciones.

Por ejemplo, en un marco web como Django o Pylons, getattrresulta sencillo asignar la URL de una solicitud web a la función que la manejará. Si miras debajo del capó del enrutamiento de Pylons, por ejemplo, verás que (al menos de forma predeterminada) divide la URL de una solicitud, como:

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

en "clientes" y "lista". Luego busca una clase de controlador llamada CustomerController. Suponiendo que encuentra la clase, crea una instancia de la clase y luego la utiliza getattrpara obtener su listmétodo. Luego llama a ese método y le pasa la solicitud como argumento.

Una vez que comprenda esta idea, resultará realmente fácil ampliar la funcionalidad de una aplicación web: simplemente agregue nuevos métodos a las clases de controlador y luego cree enlaces en sus páginas que utilicen las URL apropiadas para esos métodos. Todo esto es posible gracias a getattr.

Robert Rossney avatar Nov 02 '2010 08:11 Robert Rossney