2011-04-01 15 views
10

Sé que la pregunta es un poco raro, pero no puedo pensar en otra forma de decirlo. Tengo una aplicación que se ocupa de grandes objetos JSON, y yo quiero ser capaz de decir simplemente:¿Hay algún truco para "sobrecargar el operador de punto"?

object1.value.size.whatever.attributexyz 

en lugar de

object1.get('value').get('size').get('whatever').get('attributexyz') 

¿Hay alguna forma inteligente de coger el AttributeError que se levantó y verificar dentro de la estructura de datos si ese atributo corresponde a cualquiera de sus valores?

+0

cómo se almacenan los atributos de cada objeto? Si solo son variables de miembros regulares, en Python no es necesario hacer nada especial, solo funciona como está escrito. – bgporter

+3

, de hecho, si el objeto json es devuelto por el módulo json, debe hacer 'object1 ['value'] ['size'] ['whatever'] ['attributexyz']' para el acceso estándar al objeto –

+0

Do not diga "operador de punto", diga "acceso de atributo". Simplemente está definiendo "acceso a atributos". Python ofrece muchas formas de hacerlo. Propiedades, Decoradores y nombres de métodos especiales. Es posible que desee cambiar el título de la pregunta. –

Respuesta

18

En la definición de clase object1 's,

def __getattr__(self, key): 
    return self.get(key) 

Cualquier intento de resolver una propiedad, método o nombre del campo que no existe realmente en el objeto mismo se pasará a __getattr__.

Si no tiene acceso a la definición de la clase, es decir, es algo así como un diccionario, envuélvala en una clase. Para un diccionario, usted podría hacer algo como:

class DictWrapper(object): 
    def __init__(self, d): 
     self.d = d 
    def __getattr__(self, key): 
     return self.d[key] 

Tenga en cuenta que una KeyError se elevará si la clave no es válido; la convención, sin embargo, es levantar un AttributeError (¡gracias, S. Lott!). Se puede volver a subir el KeyError como AttributeError como tal, si es necesario:

try: 
    return self.get(key) 
except KeyError as e: 
    raise AttributeError(e) 

recordar también que si los objetos que están regresando de __getattr__ son también, por ejemplo, diccionarios, que necesitará para envolverlos demasiado .

+2

Es posible que desee utilizar 'try: self.get (key) excepto KeyError: raise AttributeError() from KeyError'. De esta manera, un atributo faltante informa un error de atributo adecuado. –

+0

@S. Lott: Muy cierto; Gracias. –

+0

Recibo un error. Parece que 'try: return self.d.get (key)' es necesario – yatsa

1

Envuelva la estructura en un objeto con el método __getattr__() adefinido. Si tiene algún control sobre la estructura, puede definir su propio __getattr___(). Getattr hace exactamente lo que quiere: "captura" los atributos que faltan y posiblemente devuelve algún valor.

0

Solo para complementar las respuestas anteriores con un ejemplo.

class A: 
    def __init__(self, *args): 
     self.args = args 

    def dump(self, *args): 
     print(self.args, args) 
     return self.args, args 

class Wrap: 
    def __init__(self, c, init_args): 
     self.c, self.init_args = c, init_args 

    def __getattr__(self, key): 
     inst = self.c(*self.init_args) 
     return getattr(inst, key) 

a = Wrap(A, (1, 2, 3)) 
a.dump(4, 5, 6) 

b = Wrap(dict, ({1:2},)) 
print(b.get(1), b.get(3)) 

# This will fail                                                         
print(b[1]) 

salidas,

$ python --version 
Python 3.6.3 
$ python wrap.py 
(1, 2, 3) (4, 5, 6) 
2 None 
Traceback (most recent call last): 
    File "wrap.py", line 24, in <module> 
    print(b[1]) 
TypeError: 'Wrap' object does not support indexing 
Cuestiones relacionadas