Definición de descriptor:
los descriptores de Python se crean para administrar los atributos de diferentes clases que usan el objeto como referencia. En los descriptores usamos tres métodos diferentes que son __getters__()
, __setters__()
y __delete__()
. Si alguno de esos métodos se define para un objeto, puede denominarse descriptor. Normalmente, Python usa métodos como getters y setters para ajustar los valores de los atributos sin ningún procesamiento especial. Es solo un sistema de almacenamiento básico. A veces, es posible que deba validar los valores que se asignan a un valor. Un descriptor es un mecanismo detrás de propiedades, métodos, métodos estáticos, métodos de clase y super()
.
Protocolo descriptor:
En otros lenguajes de programación, los descriptores se conocen como setter y getter, donde las funciones públicas se utilizan para obtener y establecer una variable privada. Python no tiene un concepto de variables privadas, y el protocolo descriptor se puede considerar como una forma Pythonic de lograr algo similar. Los descriptores son una nueva forma de implementar clases en Python y no es necesario heredar nada de un objeto en particular. Para implementar descriptores fácilmente en python, debemos usar al menos uno de los métodos definidos anteriormente. Tenga en cuenta que la instancia a continuación regresa al objeto donde se accedió al atributo, y el propietario es la clase donde se asignó el descriptor como atributo. Hay tres protocolos en el descriptor de python para establecedores, captadores y método de eliminación.
gfg.__get__(self, obj, type=None)
: Este atributo se llama cuando se quiere recuperar la información(value = obj.attr)
, y lo que devuelva es lo que se le dará al código que solicitó el valor del atributo.gfg.__set__(self, obj, value)
: Este método se llama para establecer los valores de un atributo(obj.attr = 'value')
y no le devolverá nada.gfg.__delete__(self, obj)
: Este método se llama cuando el atributo se elimina de un objeto(del obj.attr)
Descriptor de invocación:
los descriptores se invocan automáticamente cada vez que recibe la llamada para un set()
método o get()
método. Por ejemplo, obj.gfg
busque gfg en el diccionario de obj
. Si gfg define el método __get__()
, entonces gfg.__get__(obj)
se invoca. También se puede invocar directamente por el nombre del método, es decir gfg.__get__(obj)
.
# Python program showing # how to invoke descriptor def __getattribute__(self, key): v = object.__getattribute__(self, key) if hasattr(v, '__get__'): return v.__get__(None, self) return v
Los puntos importantes a recordar son:
- Los descriptores son invocados por el
__getattribute__()
método. - La anulación
__getattribute__()
evita las llamadas automáticas de descriptor. object.__getattribute__()
ytype.__getattribute__()
hacer diferentes llamadas a__get__()
.- Los descriptores de datos siempre anulan los diccionarios de instancias.
- Los diccionarios de instancias pueden anular los descriptores que no son datos.
Ejemplo de descriptor:
en este ejemplo, un descriptor de datos establece y devuelve valores normalmente e imprime un mensaje que registra su acceso.
Código 1:
class Descriptor(object): def __init__(self, name =''): self.name = name def __get__(self, obj, objtype): return "{}for{}".format(self.name, self.name) def __set__(self, obj, name): if isinstance(name, str): self.name = name else: raise TypeError("Name should be string") class GFG(object): name = Descriptor() g = GFG() g.name = "Geeks" print(g.name)
Producción:
GeeksforGeeks
Código 2:
class Descriptor(object): def __init__(self, name =''): self.name = name def __get__(self, obj, objtype): return "{}for{}".format(self.name, self.name) def __set__(self, obj, name): if isinstance(name, str): self.name = name else: raise TypeError("Name should be string") class GFG(object): name = Descriptor() g = GFG() g.name = "Computer" print(g.name)
Producción:
ComputerforComputer
Creando un Descriptor usando property() :property()
, es fácil crear un descriptor usable para cualquier atributo. Sintaxis para crearproperty()
property(fget=None, fset=None, fdel=None, doc=None)
# Python program to explain property() function # Alphabet class class Alphabet: def __init__(self, value): self._value = value # getting the values def getValue(self): print('Getting value') return self._value # setting the values def setValue(self, value): print('Setting value to ' + value) self._value = value # deleting the values def delValue(self): print('Deleting value') del self._value value = property(getValue, setValue, delValue, ) # passing the value x = Alphabet('GeeksforGeeks') print(x.value) x.value = 'GfG' del x.value
Producción :
Getting value GeeksforGeeks Setting value to GfG Deleting value
Creando un Descriptor usando métodos de clase:
En esto creamos una clase y anulamos cualquiera de los métodos del descriptor __set__
, __ get__
y __delete__
. Este método se utiliza cuando se necesita el mismo descriptor en muchas clases y atributos diferentes, por ejemplo, para la validación de tipos.
class Descriptor(object): def __init__(self, name =''): self.name = name def __get__(self, obj, objtype): return "{}for{}".format(self.name, self.name) def __set__(self, obj, name): if isinstance(name, str): self.name = name else: raise TypeError("Name should be string") class GFG(object): name = Descriptor() g = GFG() g.name = "Geeks" print(g.name)
Producción :
GeeksforGeeks
Creación de un descriptor usando @property Decorator:
en esto usamos el poder de los decoradores de propiedades que son una combinación del método de tipo de propiedad y los decoradores de Python.
class Alphabet: def __init__(self, value): self._value = value # getting the values @property def value(self): print('Getting value') return self._value # setting the values @value.setter def value(self, value): print('Setting value to ' + value) self._value = value # deleting the values @value.deleter def value(self): print('Deleting value') del self._value # passing the value x = Alphabet('Peter') print(x.value) x.value = 'Diesel' del x.value
Producción :
Getting value Peter Setting value to Diesel Deleting value
Publicación traducida automáticamente
Artículo escrito por Jitender_1998 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA