📜  Python中的描述符

📅  最后修改于: 2022-05-13 01:54:34.818000             🧑  作者: Mango

Python中的描述符

描述符的定义:
创建Python描述符是为了管理使用对象作为引用的不同类的属性。在描述符中,我们使用了三种不同的方法,即__getters__()__setters__()__delete__() 。如果为对象定义了这些方法中的任何一个,则可以将其称为描述符。通常, Python使用 getter 和 setter 等方法来调整属性的值,而无需任何特殊处理。它只是一个基本的存储系统。有时,您可能需要验证分配给某个值的值。描述符是属性、方法、静态方法、类方法和super()背后的机制。描述符协议:
在其他编程语言中,描述符被称为 setter 和 getter,其中公共函数用于获取和设置私有变量。 Python没有私有变量的概念,描述符协议可以被认为是一种 Python 的方式来实现类似的东西。描述符是在Python中实现类的一种新方法,它不需要从特定对象继承任何东西。为了在Python中轻松实现描述符,我们必须至少使用上面定义的方法之一。请注意,下面的实例返回到访问属性的对象,所有者是描述符被分配为属性的类。 Python描述符中有 setter、getter 和 delete 方法的三个协议。

  • gfg.__get__(self, obj, type=None) :当您想要检索信息时调用此属性(value = obj.attr) ,并且无论它返回什么都将提供给请求该属性值的代码。
  • gfg.__set__(self, obj, value) :调用此方法来设置属性的值(obj.attr = 'value') ,它不会向您返回任何内容。
  • gfg.__delete__(self, obj) :从对象中删除属性时调用此方法(del obj.attr)


调用描述符:
每当收到对set()方法或get()方法的调用时,就会自动调用描述符。例如, obj.gfgobj的字典中查找 gfg。如果 gfg 定义了方法__get__() ,则gfg.__get__(obj)被调用。它也可以通过方法名直接调用,即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

要记住的要点是:

  • 描述符由__getattribute__()方法调用。
  • 覆盖__getattribute__()可防止自动描述符调用。
  • object.__getattribute__()type.__getattribute__() __get__()不同的调用。
  • 数据描述符总是覆盖实例字典。
  • 实例字典可以覆盖非数据描述符。


描述符示例:
在此示例中,数据描述符正常设置和返回值,并打印一条记录其访问的消息。
代码 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)

输出:

GeeksforGeeks


代码 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)

输出:

ComputerforComputer


使用 property() 创建描述符:
property() ,很容易为任何属性创建一个可用的描述符。创建property()

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 

输出 :

Getting value
GeeksforGeeks
Setting value to GfG
Deleting value

使用类方法创建描述符:
在此我们创建一个类并覆盖任何描述符方法__set____ get____delete__ 。当许多不同的类和属性需要相同的描述符时使用此方法,例如,用于类型验证。

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)

输出 :

GeeksforGeeks


使用 @property Decorator 创建描述符:
在此我们使用属性装饰器的强大功能,它是属性类型方法和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 

输出 :

Getting value
Peter
Setting value to Diesel
Deleting value