Descriptor en Python

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.gfgbusque 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__()y type.__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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *