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

3 views
Skip to first unread message

Kiko

unread,
Dec 14, 2015, 4:11:06 PM12/14/15
to La lista de python en castellano
Hola.

Necesito identificar si un atributo de una clase es un descriptor.

Por ejemplo, para conocer los descriptores del built-in type int usaría lo siguiente:

import types
a = 1
for attr in dir(a):
    if isinstance(getattr(type(a), attr), types.GetSetDescriptorType):
        print(attr)

Y el resultado sería:

denominator
imag
numerator
real

Que creo son los únicos descriptores de int.

¿Es esto correcto?
¿Un descriptor puede ser otra cosa que no sea types.GetSetDescryptorType?

Gracias.

Saludos.

Kiko

unread,
Dec 14, 2015, 4:18:08 PM12/14/15
to La lista de python en castellano
El 14 de diciembre de 2015, 22:10, Kiko <kikoco...@gmail.com> escribió:
Hola.

Necesito identificar si un atributo de una clase es un descriptor.

Por ejemplo, para conocer los descriptores del built-in type int usaría lo siguiente:

import types
a = 1
for attr in dir(a):
    if isinstance(getattr(type(a), attr), types.GetSetDescriptorType):
        print(attr)

Y el resultado sería:

denominator
imag
numerator
real


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...

:-(
 
Que creo son los únicos descriptores de int.

¿Es esto correcto?

Pues parece que no.
 
¿Un descriptor puede ser otra cosa que no sea types.GetSetDescryptorType?


¿Alguna ayuda para poder detectar descriptores?
 
Gracias.


De nuevo.
 
Saludos.

Kiko

unread,
Dec 14, 2015, 4:24:48 PM12/14/15
to La lista de python en castellano
 
import types
a = 1
for attr in dir(a):
    if isinstance(getattr(type(a), attr), types.GetSetDescriptorType):
        print(attr)

Y el resultado sería:

denominator
imag
numerator
real


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?

Gracias.

Chema Cortes

unread,
Dec 14, 2015, 10:11:18 PM12/14/15
to La lista de python en castellano
Oficialmente, un descriptor es todo objeto con, al menos, un método "__get__":

hasattr(attr, "__get__")
 

Gracias.
_______________________________________________
Python-es mailing list
Pyth...@python.org
https://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/
--
Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales": http://ch3m4.org/blog

Kiko

unread,
Dec 15, 2015, 3:22:23 AM12/15/15
to La lista de python en castellano
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_method

In [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):

In [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.

Chema Cortes

unread,
Dec 15, 2015, 4:26:30 AM12/15/15
to La lista de python en castellano
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.

 


_______________________________________________
Python-es mailing list
Pyth...@python.org
https://mail.python.org/mailman/listinfo/python-es
FAQ: http://python-es-faq.wikidot.com/

Kiko

unread,
Dec 15, 2015, 4:40:31 AM12/15/15
to La lista de python en castellano
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.

Chema Cortes

unread,
Dec 15, 2015, 5:30:23 AM12/15/15
to La lista de python en castellano
El mar., 15 dic. 2015 a las 10:40, Kiko (<kikoco...@gmail.com>) escribió:

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

Más que complicado, los descriptores es lo que da a python toda su "magia".
 

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?


Creo que empiezo a entender lo que quieres. Lo que denominas "propiedad", o simplemente "descriptor", sería lo que se conoce como "descriptor de datos". Son los descriptores a los que se pueden asignar valores, para entendernos. Para ser "descriptor de datos" basta con tener un método "__set__":

props = [attr for attr in dir(a) if hasattr(type(a), attr) and hasattr(getattr(type(a),attr), "__set__")]

Los tipos "GetSetDescriptorType" y "MemberDescriptorType" son usados por los módulos de extensión, los que se compilan desde C en el caso de CPython. Pero es mucho más genérico indagar por atributos "__get__" y "__set__" para saber si son descriptores, además de funcionar siempre.


Chema Cortes

unread,
Dec 15, 2015, 5:42:59 AM12/15/15
to La lista de python en castellano
El mar., 15 dic. 2015 a las 11:30, Chema Cortes (<pyc...@gmail.com>) escribió:
El mar., 15 dic. 2015 a las 10:40, Kiko (<kikoco...@gmail.com>) escribió:

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

Más que complicado, los descriptores es lo que da a python toda su "magia".
 

En mi viejo blog tengo una serie de artículos explicando el funcionamiento de los descriptores. Voy a migrarlo ya, pero aún se puede encontrar en su vieja ubicación:

http://ch3m4.org/blog/tag/descriptor/


Kiko

unread,
Dec 15, 2015, 5:46:44 AM12/15/15
to La lista de python en castellano
El 15 de diciembre de 2015, 11:42, Chema Cortes <pyc...@gmail.com> escribió:


El mar., 15 dic. 2015 a las 11:30, Chema Cortes (<pyc...@gmail.com>) escribió:
El mar., 15 dic. 2015 a las 10:40, Kiko (<kikoco...@gmail.com>) escribió:

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

Más que complicado, los descriptores es lo que da a python toda su "magia".
 

En mi viejo blog tengo una serie de artículos explicando el funcionamiento de los descriptores. Voy a migrarlo ya, pero aún se puede encontrar en su vieja ubicación:

http://ch3m4.org/blog/tag/descriptor/

Pues tendré que ponerme a estudiar para poder entender un poco mejor todas las interioridades.

Gracias, Chema.
 



--
Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales": http://ch3m4.org/blog

Reply all
Reply to author
Forward
0 new messages