¿Cuál es el mejor enfoque para crear dinámicamente y hacer referencia a los atributos anidados?Anulación de __getattr__ para admitir atributos anidados dinámicos
Escribía un cliente simple de Flickr y quería hacer coincidir la API documentada lo más posible, sin definir realmente cada método. Por ejemplo, para hacer una petición a Flickr de flickr.people.getInfo
API method:
flickr = Client()
data = flickr.people.getInfo(user_id='xxx')
En este caso flickr.people.getInfo
Se correlaciona directamente con el método correspondiente en su documentación de la API. Cuando se llaman, people
y getInfo
se crean a medida que se buscan, luego la solicitud correcta se determina por la ruta al getInfo
, que es people.getInfo
. Este es el enfoque que utilicé:
class Attr(object):
def __init__(self, client, name, parent):
self._client = client
self._name = name
self._parent = parent
def __getattr__(self, name):
attr = Attr(self._client, name, self)
setattr(self, name, attr)
return attr
def _get_path(self, path=None):
if path:
path = '.'.join((self._name, path))
else:
path = self._name
if isinstance(self._parent, Attr):
return self._parent._get_path(path)
return path
def __call__(self, *args, **kwargs):
return self._client.execute_method(self._get_path(), *args, **kwargs)
class Client(object):
def __getattr__(self, name):
attr = Attr(self, name, None)
setattr(self, name, attr)
return attr
def execute_method(self, method, *args, **kwargs):
print method, args, kwargs
Esto funciona, pero tengo curiosidad si mi enfoque para tratar con asignación de atributo anidado/operaciones de búsqueda se puede mejorar, o si hay algún error al acecho en espera, sin yo saberlo . En particular, tengo curiosidad de saber si hay una mejor manera de descubrir el "camino" hacia un atributo dado. Por ejemplo, si llamo a Client().x.y.z()
, x
, y
, z
no existo, y se crearán uno por uno (como __getattr__
busca un solo atributo a la vez). Cuando se llama al z
, necesito poder discernir que la ruta al z
es x.y.z
.
atributos "superpuestas" son casi siempre manejado con objetos anidados. ¿Por qué estás analizando el nombre, cuando Python puede manejar este análisis por ti? –
Estoy creando objetos anidados. ¿Hay alguna manera más sencilla de descubrir el camino hacia un atributo anidado? – zeekay
Cuando haces 'a.b.c', Python da' 'b '' a' a' '__getattr__'. No necesita razonar un "camino" ni nada parecido. Solo debe proporcionar la instancia adecuada de 'b' en' a.b' y la instancia adecuada de 'c' y' b.c'. –