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

Kiko kikocorreoso en gmail.com
Mar Dic 15 03:22:06 EST 2015


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.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20151215/c9997aba/attachment.html>


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