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.gfg
在obj
的字典中查找 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