¿Cómo puedo devolver un valor predeterminado para un atributo? [duplicar]
Esta pregunta ya tiene una respuesta aquí:
Tengo un objeto "myobject
", que podría devolver None
. Si devuelve None
, no devolverá un atributo "id
":
a = myobject.id
Así que cuando myobject es None
, el stament anterior resulta en un AttributeError:
AttributeError: 'NoneType' object has no attribute 'id'
Si myobject
es Ninguno, entonces quiero que "a
" sea igual a Ninguno. ¿Cómo puedo evitar esta excepción en una declaración de línea, como:
a= default(myobject.id, None)
7 answers
Debe utilizar el getattr
wrapper en lugar de recuperar directamente el valor de id
.
a = getattr(myobject, 'id', None)
Esto es como decir "Me gustaría recuperar el atributo id
del objeto myobject
, pero si no hay ningún atributo id
dentro del objeto myobject
, entonces devuelve None
en su lugar."Pero lo hace eficientemente.
Algunos objetos también admiten la siguiente forma de acceso getattr
:
a = myobject.getattr('id', None)
Según la solicitud de OP, 'deep getattr':
def deepgetattr(obj, attr):
"""Recurses through an attribute chain to get the ultimate value."""
return reduce(getattr, attr.split('.'), obj)
# usage:
print deepgetattr(universe, 'galaxy.solarsystem.planet.name')
Simple explicación:
Reduce es como una función recursiva en el lugar. Lo que hace en este caso es comenzar con el obj
(universo) y luego recursivamente obtener más profundo para cada atributo que intenta acceder usando getattr
, por lo que en su pregunta sería así:
a = getattr(getattr(myobject, 'id', None), 'number', None)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-25 16:23:32
La forma más sencilla es usar el operador ternario:
a = myobject.id if myobject is not None else None
El operador ternario devuelve la primera expresión si el valor medio es true, de lo contrario devuelve la última expresión.
Tenga en cuenta que también podría hacer esto de otra manera, utilizando excepciones:
try:
a = myobject.id
except AttributeError:
a = None
Esto encaja con el ideal pitónico de que es más fácil pedir perdón que permiso - lo que es mejor dependerá de la situación.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-17 16:49:44
En mi clase object puedes poner override
class Foo(object):
def __getattribute__(self, name):
if not name in self;
return None;
else:
# Default behaviour
return object.__getattribute__(self, name)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-17 16:57:12
Ayuda sobre la función integrada getattr en el módulo builtins:
getattr(...) getattr(object, name[, default]) -> value
Obtiene un atributo con nombre de un objeto; getattr(x, 'y') es equivalente a x.y. Cuando se da un argumento predeterminado, se devuelve cuando el atributo no existe; sin ella, se plantea una excepción en ese caso.
Lo siguiente debería funcionar:
a = getattr(myobject, 'id', None)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-17 16:59:57
Si desea resolver el problema en la definición de la clase de myobject
(como en Black Diamond's answer ), simplemente puede definir __getattr__
para devolver None
:
class Myobject:
def __getattr__(self, name):
return None
Esto funciona porque __getattr__
solo se llama cuando se intenta acceder a un atributo que no existe, mientras que __getattribute__
siempre se llama primero sin importar el nombre del atributo. (Véase también este post.)
Para probar:
myobject = Myobject()
print myobject.id
myobject.id = 7
print myobject.id
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-30 18:45:35
try:
a = myobject.id
except AttributeError:
a = None
También funcionará y es más claro, IMO
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-17 16:51:17
a=myobect.id if myobject else None
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-17 16:53:54