cuando digo "atributo pitón de búsqueda proccess" quiero decir: ¿qué pitón hace cuando se escribe x.foo ??¿Cómo funciona el proceso de búsqueda de atributos python?
Buscando en la web y no encontré a mucha documentación acerca de esto, uno de los mejores papeles que encontré reanudó la proccess a los siguientes pasos (se puede ver el artículo completo here)
- Si es attrname un atributo especial (es decir, Python-provided) para objectname, lo devuelve.
- Comprobar objectname .__ clase __.__ dict__ para attrname. Si existe y es un descriptor de datos, devuelva el resultado del descriptor. Buscar todas las bases de objectname .__ class__ para el mismo caso.
- Comprobar objectname .__ dict__ para attrname, y volver si se encuentra. Si objectname es una clase, busca sus bases también. Si es una clase y existe un descriptor en ella o sus bases, devuelva el resultado del descriptor.
- Comprobar objectname .__ clase __.__ dict__ para attrname. Si existe y no es un descriptor de datos, devuelva el resultado del descriptor. Si existe, y no es un descriptor, simplemente devuélvalo. Si existe y es un descriptor de datos, no deberíamos estar aquí porque hubiéramos regresado en el punto 2. Buscar todas las bases de objectname .__ class__ para el mismo caso.
- Elevar AttributeError.
Al principio esto puede parecer correcto, pero el proceso de búsqueda de atributos es un poco más complicado, por ejemplo para x.foo, no se comporta igual si x es una clase o una instancia.
he encontrado un algunas muestras que no pueden ser explicados por este camino. Considere el siguiente código Python:
class Meta(type):
def __getattribute__(self, name):
print("Metaclass getattribute invoked:", self)
return type.__getattribute__(self, name)
def __getattr__(self, item):
print('Metaclass getattr invoked: ', item)
return None
class C(object, metaclass=Meta):
def __getattribute__(self, name):
print("Class getattribute invoked:", args)
return object.__getattribute__(self, name)
c=C()
Ahora compruebe las siguientes líneas con la salida correspondiente:
>> C.__new__
Metaclass getattribute invoked: <class '__main__.C'>
<built-in method __new__ of type object at 0x1E1B80B0>
>> C.__getattribute__
Metaclass getattribute invoked: <class '__main__.C'>
<function __getattribute__ at 0x01457F18>
>> C.xyz
Metaclass getattribute invoked: <class '__main__.C'>
Metaclass getattr invoked: xyz
None
>> c.__new__
Class getattribute invoked: (<__main__.C object at 0x013E7550>, '__new__')
<built-in method __new__ of type object at 0x1E1B80B0>
>> c.__getattribute__
Class getattribute invoked: (<__main__.C object at 0x01438DB0>, '__getattribute__')
Metaclass getattribute invoked: <class '__main__.C'>
<bound method C.__getattribute__ of <__main__.C object at 0x01438DB0>>
>>
Las conclusiones son que he estado (teniendo en cuenta que estamos buscando x.foo):
- __getattribute__ es diferente para las instancias de < tipo 'tipo'> y < tipo 'objeto'>. Para C.foo(), 'foo' se busca primero en C .__ dict__ y se devuelve si se encuentra (en lugar del tipo de búsqueda (C)) y para x.foo() 'foo' se busca en tipo (x) .__ dict__ y en x .__ dict__.
- __getattribute__ método siempre se resuelve en el tipo (x), lo que no entiendo aquí es el último caso: c .__ getattribute__, no es objeto contiene un método __getattribute__ (y C hereda del objeto), entonces ¿por qué metaclass El método getattribute se llama.
Puede alguien explicar esto, por favor ?? o al menos dime dónde puedo encontrar documentación sobre esto, gracias.
Tipos y objetos de Python http://www.cafepy.com/article/python_types_and_objects/ – amirouche