2009-12-15 10 views
12

Python's setdefault le permite obtener un valor de un diccionario, pero si la clave no existe, entonces asigne el parámetro basado en default. Luego, busca lo que esté en la llave del diccionario.En python, ¿hay un equivalente de setdefault() para obtener atributos de objeto?

Sin manipular un objeto __dict__ ¿Existe una función similar para los objetos?

p. Ej.
Tengo un objeto foo que puede o no tener el atributo bar. ¿Cómo puedo hacer algo como:

result = setdefaultattr(foo,'bar','bah') 

Respuesta

6

Python no tiene uno integrado, pero se puede definir su propio:

def setdefaultattr(obj, name, value): 
    if not hasattr(obj, name): 
     setattr(obj, name, value) 
    return getattr(obj, name) 
+0

¿Qué pasa con 'def setdefaultattr (o, n, v): return setdefault (o .__ dict__, n, v)'? Sin embargo, eso no funcionaría en las clases con máquinas tragamonedas. –

1
vars(obj).setdefault(name, value) 
+0

Entonces, vars() simplemente devuelve obj .__ dict__? –

+0

(Prefiero la sintaxis de var() a obj .__ dict__) –

+1

@Ross seguro. ver 'help (vars)' –

19

Tenga en cuenta que la respuesta será aceptado en la actualidad, si el El atributo ya no existe, ha llamado a hasattr(), setattr() y getattr(). Esto sería necesario solo si el OP hubiera hecho algo así como reemplazar el setattr y/o getattr, en cuyo caso el OP no es el investigador inocente para el que lo tomamos. De lo contrario, llamar a las 3 funciones es bruto; la llamada setattr() debe ser seguido por return value para que no se caiga a través de return getattr(....)

De acuerdo con la docs, hasattr() se implementa llamando getattr() y la captura de excepciones. El siguiente código puede ser más rápido cuando ya existe el atributo:

def setdefaultattr(obj, name, value): 
    try: 
     return getattr(obj, name) 
    except AttributeError: 
     setattr(obj, name, value) 
    return value 
+1

+1 para EAFP (captura de excepciones) – tzot

+0

¿Por qué esto no funcionaría si el objeto tuviera un 'setattr' y/o' getattr' anulado? – martineau

+0

el método vars (obj) es un poco más rápido de mi prueba (alrededor del 5%) – sbaechler

0

No hacer esto.

Por favor.

Utilice __init__ para proporcionar valores predeterminados. Por favor. Esa es la manera Ptónica.

class Foo(object): 
    def __init__(self): 
     self.bar = 'bah' 

Este es el enfoque normal, estándar y típico. No hay una razón convincente para hacer lo contrario.

+1

Tienes razón. Lástima de mí :-) Debería ir a arreglar la función __init__. –

+0

@Ross Rogers: por favor hazlo. –

+0

Podría haber motivos para hacer lo que se solicitó, p. Ej. el almacenamiento en caché de resultados temporales en propiedades, que solo necesita, cuando el atributo realmente se lee. Además de eso, lo que estás haciendo en tu ejemplo debería ser una barra variable de clase simple. Lo que estás haciendo es hinchar cada objeto sin razón. – Michael

Cuestiones relacionadas