Descriptor en Python

| | | | | | | | | | | | | | | | |

Protocolo de descriptor:
En otros lenguajes de programación, los descriptores se denominan 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 como esto. Descriptores — es una nueva forma de implementar clases en Python y no necesita heredar nada de un objeto en particular. Para implementar fácilmente descriptores en python, debemos usar al menos uno de los métodos definidos anteriormente. Tenga en cuenta que la siguiente instancia devuelve el objeto al que accedió el atributo y que el propietario es la clase en la que se asignó el identificador como atributo. Hay tres protocolos en el descriptor de Python para setters, getters y un método de eliminación.

  • gfg .__ get __ (self, obj, type = None) : Este atributo se llama cuando desea obtener la información (value = obj.attr) y lo que devuelve es — esto es lo que se pasará al código que solicitó el valor del atributo.
  • gfg .__ set __ (self, obj, value) : se llama a este método para establecer los valores de atributo ‚Äã‚Äã(obj .attr = &# 39; valor ') y no le devolverá nada.
  • gfg .__ delete __ (self, obj) : este método se llama cuando se elimina un atributo de un objeto (del obj.attr)

Invocación de descriptor:
Los descriptores se invocan automáticamente cuando se recibe una invocación para el método set() o get() . Por ejemplo, obj.gfg busca gfg en el diccionario obj . Si gfg define un método __get __ () , entonces gfg .__ get __ (obj) . También se puede llamar directamente por el nombre del método, es decir, gfg .__ get __ (obj) .


# Mostrar el programa Python
# cómo llamar al descriptor

def __ getattribute __ ( self , clave):

v = objeto .__ getattribute __ ( self , clave)

if hasattr (v, `__get__` ):

return v .__ obtener __ ( Ninguno , self )

return v

Puntos importantes para recordar:

  • Los descriptores son llamados por el método __getattribute __ () .
  • Sobrescribir __getattribute__ () evita llamadas automáticas al descriptor.
  • object .__ getattribute __ () y type .__ getattribute __ () varias 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.

Un ejemplo de un descriptor:
En este ejemplo, un descriptor de datos generalmente establece y devuelve valores ​​e imprime un mensaje que registra su acceso.
Código 1:


clase Descriptor ( objeto < clase de código = "simple">):

def __ init __ ( self , name = ` `):

self . nombre = nombre


def __ get __ ( self , obj, tipoobj):

return " {} for {} "< /código> . formato ( self .name, self .name)

def __ set __ ( self , obj, nombre):

if esinstancia (nombre, str ):

self . nombre = nombre

otro :

aumentar TypeError ( " El nombre debe ser cadena " )


class GFG ( objeto ):

nombre = Descriptor ()

g = GFG ()

g.name = "Geeks"

imprimir (g.name)

Salir:

Python.Engineering

Código 2:


< tbody>

clase Descriptor ( objeto ):


def __ init __ ( self , name = < código clase = "simple"> ` `):

self . nombre = nombre


def __ get __ ( self , obj, tipoobj):

volver "{} para {}" . formato ( self .name, self .name)


def __ set __ ( self , obj, nombre ):

if isinstance ( nombre, str ):

self . nombre = nombre

más :

raise TypeError ( "Name should be string" )


class GFG ( objeto ):

nombre = < /código> Descriptor ()


g = GFG ()

g.name = "Computadora"

imprimir ( g.nombre)

Salir:

 ComputerforComputer 

Cree un identificador usando la propiedad ():
property () , es fácil crear un descriptor utilizable para cualquier atributo. Sintaxis para crear la propiedad property()

 (fget = Ninguno, fset = Ninguno, fdel = Ninguno, doc = Ninguno) 

< table border = "0" cellpadding = "0" cellpacing = "0">

# Programa Python para explicar la propiedad ( ) función


# Clase de alfabeto

class Alfabeto:

def __ init __ ( self , valor):

self ._ valor = valor


# obtener valores ​​

def getValue ( se lf ):

print ( `Obteniendo valor` )

retorno self ._ valor


# valores de instalación ‚Äã‚Äã

def setValue ( self , valor):

imprimir ( `Establecer valor en` + valor)

self ._ value = valor


# remo ve valores ​​

def delValue ( self ):

print ( `Eliminar valor` )

del < /código> self ._ valor


valor = propiedad (getValue, setValue, delValue,)


# pasar el valor

x = Alfabeto ( `GeeksforGeeks` )

imprimir (x.valor)


x.valor = `GfG`

del x.valor

Salir:

 Obtener valor Python.Engineering Establecer valor para GfG Eliminar valor 

Generando un descriptor usando métodos de clase:
En esto creamos Vamos a obtener la clase y anular cualquiera de los métodos del descriptor __set__ , __ get__ y __delete__ . Este método se usa cuando se requiere el mismo descriptor para muchas clases y atributos diferentes, por ejemplo, para la verificación de tipos.


class Descriptor ( objeto ):

def < clase de código ="simple "> __ init__ ( self , nombre = ` `):

self < /código> .nombre = nombre

def __ obtener __ ( < código class = "color1"> self , obj, objtype):

return " {} para {} " . formato ( self .name, self .name)


def __ set __ ( self , obj, nombre ):

if isinstance (nombre, str ):

self . nombre = nombre

otro :

aumentar TypeError ( "El nombre debe ser una cadena" )


clase GFG ( objeto ):

nombre = Descriptor ()


g = GFG ( )

g.name = "Geeks "

print (g.name)

< /código>

Resultado:

 Python.Engineering 

Crear un descriptor usando @property Decorador:
En este usamos el poder de los decoradores de propiedades, que son una combinación de un método de tipo de propiedad y decoradores de Python.


class Alfabeto:

def __ init __ ( self , valor):

self ._ valor = value


# recuperando los valores ​​

@ propiedad

def valor ( self ):

imprimir ( `Obteniendo valor` )

return self ._ value

# configuración de valores ‚Äã‚Äã

< código clase = "decorador"> @ valor . setter

def value ( self , valor):

imprimir ( `Establecer valor en ` + valor)

self ._ valor = valor


# eliminar valores ​​

@ valor .eliminar

def valor ( self ):

imprimir ( `Borrar valor` )

del self ._ valor



# pasar el valor

x = Alfabeto ( `Peter` )

imprimir (x.value)


x.value = `Diesel`


del x.value

Salir:

 Obteniendo valor Peter Estableciendo valor a Diesel Borrando valor