[Python-es] Saber si un atributo es un descriptor

Kiko kikocorreoso en gmail.com
Mar Dic 15 04:40:27 EST 2015


El 15 de diciembre de 2015, 10:26, Chema Cortes <pych3m4 en gmail.com>
escribió:

>
>
> El mar., 15 dic. 2015 a las 9:22, Kiko (<kikocorreoso en gmail.com>)
> escribió:
>
>> El 15 de diciembre de 2015, 4:11, Chema Cortes <pych3m4 en gmail.com>
>> escribió:
>>
>>>
>>>
>>> El lun., 14 dic. 2015 a las 22:24, Kiko (<kikocorreoso en gmail.com>)
>>> escribió:
>>>
>>>>
>>>>
>>>>> *import types*
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> *a = 1for attr in dir(a):    if isinstance(getattr(type(a), attr),
>>>>>> types.GetSetDescriptorType):        print(attr)*
>>>>>> Y el resultado sería:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> *denominatorimagnumeratorreal*
>>>>>>
>>>>>
>>>>> Vaya, acabo de cambiar *a* para que sea *complex* en lugar de *int* y
>>>>> mi código de encima no me devuelve *img* y *real*, que son
>>>>> descriptores de *complex*...
>>>>>
>>>>> :-(
>>>>>
>>>>
>>>> Esto parece que sí funciona:
>>>>
>>>> *import types*
>>>> *a = 1 + 2j*
>>>>
>>>>
>>>>
>>>> *for attr in dir(a):    if isinstance(getattr(type(a), attr), *
>>>>
>>>>
>>>> *                      (types.GetSetDescriptorType,
>>>> types.MemberDescriptorType)):        print(attr)*
>>>> Lo anterior parece que sí funciona. No entiendo muy bien la diferencia
>>>> entre GetSetDescriptor y MemberDescriptor.
>>>> ¿Sería lo anterior lo adecuado para resolver el problema?
>>>>
>>>
>>> Oficialmente, un descriptor es todo objeto con, al menos, un método
>>> "__get__":
>>>
>>> hasattr(attr, "__get__")
>>>
>>
>> Eso había leído, sí, y así es. Pero lo que me confunde es cuando aquí
>> definen como se invocan (TL&DR, lo llaman como un atributo):
>> https://docs.python.org/3.5/howto/descriptor.html#invoking-descriptors
>>
>> Aquí definen las *properties*, que creía que era lo que buscaba en un
>> principio:
>> https://docs.python.org/3.5/howto/descriptor.html#properties
>> Pero algunos atributos que actúan como *properties* no son instancias de
>> *property*...
>>
>> Lo que estoy buscando, y no me he explicado bien por desconocimiento,
>> como muchas otras veces, es saber si 'algo' actúa como una *property*,
>> es decir, la puedo invocar como un atributo pero no es un atributo.
>>
>> Por ejemplo:
>>
>>
>>
>>
>>
>>
>> * In [1]: type(int.from_bytes)Out[1]: builtin_function_or_methodIn [2]:
>> type(int.numerator)Out[2]: getset_descriptor*
>> De ahí pensaría que* from_bytes* es un método (y también es un
>> descriptor, como bien indicas):
>>
>> I
>>
>>
>>
>> *n [3]: int.to_bytes.__get__Out[3]: <method-wrapper '__get__' of
>> method_descriptor object at 0x01283328>In [4]: int.numerator.__get__Out[4]:
>> <method-wrapper '__get__' of getset_descriptor object at 0x012835F8>*
>>
>> Lo que busco es si un descriptor se puede llamar como un atributo (como
>> si fuera una property). Lo siguiente me devuelve *False*:
>>
>> In [5]: isinstance(int.numerator, property)
>> Out[5]: False
>>
>> In [6]: callable(int.numerator)
>> Out[6]: False
>>
>> Lo que me indica que* numerator* no es una *property* pero tampoco en un
>> atributo al uso (un atributo al uso también deviuelve *False* con las
>> dos comprobaciones anteriores).
>>
>> Por tanto, vuelvo a mi pregunta inicial reformulada gracias a las
>> indicaciones de Chema:
>>
>> ¿Puedo comprobar si un descriptor funciona como un atributo de clase con
>> el siguiente código?
>>
>>
>> *import types*
>> *a = 1 + 2j*
>>
>>
>>
>> *for attr in dir(a):    if isinstance(getattr(type(a), attr), *
>>
>> *                      (types.GetSetDescriptorType,
>> types.MemberDescriptorType)):        print(attr)*
>>
>> Es decir, ¿un descriptor que funciona como una *property*, atributo,...,
>> solo puede ser instancia de* types.GetSetDescriptorType *o
>>
>> * types.MemberDescriptorType?*
>> A ver si ahora he atinado más con la pregunta.
>>
>> Disculpas por el cambalache y gracias, Chema.
>>
>
> Si has oído que python usa "duck types", este sería el caso ilustrativo.
> Descriptores son todo objeto que tenga un atributo "__set__" o "__get__",
> independiente de como haya sido creado. Y está implícito en el
> funcionamiento de python hasta el punto de que puedes crear propiedades
> como descriptores, sin derivar necesariamente desde property. Así mismo, un
> "callable" es todo objeto que tenga un atributo "__call__" que, además de
> incluir funciones y métodos, también son las clases que usan "__call__"
> para la creación de instancias (No confundas 'descriptor' con 'callable').
>
> Se ha intentado formalizar el "duck typing" mediantes clases abstractas
> (ver módulo 'abc').
>
> Si no te aclaras, lo mejor es que pongas algo de código de lo que quieres
> y te podría dar alguna pista.
>

Como diría ese gran estadista, "It is very difficult, todo esto".

Creo que lo anterior resume, creo, lo que quiero:

¿Puedo comprobar si un descriptor funciona como un atributo de clase o como
una *property* con el siguiente código?
Cuando me refiero a descriptores en mi contexto de ignorancia supina estoy
refiriéndome a cosas como *int.numerator, complex.real,...*

*import types*
*a = 1 + 2j*



*for attr in dir(a):    if isinstance(getattr(type(a), attr), *

*                      (types.GetSetDescriptorType,
types.MemberDescriptorType)):        print(attr)*

Es decir, ¿un descriptor que funciona como una *property*, atributo,...,
solo puede ser instancia de* types.GetSetDescriptorType *o*
types.MemberDescriptorType?*

Gracias.

Saludos.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20151215/547b97c1/attachment.html>


Más información sobre la lista de distribución Python-es