Python描述符(Descriptor)入门
简介
Python描述符(Descriptor)是一个高级概念,允许程序员将某些功能捆绑到类属性上。描述符可以实现特定的访问控制、计算属性和方法绑定等功能。
描述符是Python用于实现属性访问控制的重要机制之一。可以将描述符看作是实现对属性赋值所产生的行为进行拦截的机制。
这里将详细讲解Python描述符的实现方法及使用场景。
标准的Python描述符方法
__get__(self, instance, owner)
当一个属性被访问时,__get__
方法被调用。其中,self
是访问属性对象(对象的实例),instance
是访问对象的属性的实例本身,owner
是类对象。
以下示例说明:
class Descriptor:
def __get__(self, instance, owner):
print(f"get {self} from {instance} - {owner}")
return self
class Test:
attr = Descriptor()
t = Test()
t.attr
输出:
get <__main__.Descriptor object at 0x7fda7ac53a90> from <__main__.Test object at 0x7fda7ac53e20> - <class '__main__.Test'>
<__main__.Descriptor object at 0x7fda7ac53a90>
__set__(self, instance, value)
当一个属性被赋值时,__set__
方法被调用。其中,self
是访问属性对象,instance
是访问对象的属性的实例本身,value
是被赋的值。
以下示例说明:
class Descriptor:
def __set__(self, instance, value):
print(f"set {self} to {value} from {instance}")
instance._attr = value
class Test:
attr = Descriptor()
t = Test()
t.attr = 1
输出:
set <__main__.Descriptor object at 0x7fda7ac53400> to 1 from <__main__.Test object at 0x7fda7ac53940>
__delete__(self, instance)
当一个属性被删除时,__delete__
方法被调用。其中,self
是访问属性对象,instance
是访问对象的属性的实例本身。
以下示例说明:
class Descriptor:
def __delete__(self, instance):
print(f"delete {self} from {instance}")
del instance._attr
class Test:
attr = Descriptor()
t = Test()
t.attr = 1
del t.attr
输出:
set <__main__.Descriptor object at 0x7ff180079820> to 1 from <__main__.Test object at 0x7ff1800796a0>
delete <__main__.Descriptor object at 0x7ff180079820> from <__main__.Test object at 0x7ff1800796a0>
描述符应用场景
限制属性值的取值范围
描述符可以用来限制属性值的取值范围。可以通过定义一个描述符来限制属性值在一定范围内。以下示例限制属性值在0到100之间:
class RangeValue:
def __init__(self, minimum=None, maximum=None):
self.minimum = minimum
self.maximum = maximum
def __get__(self, instance, owner):
return instance._attr
def __set__(self, instance, value):
if self.minimum is not None and value < self.minimum:
raise ValueError(f"Value {value} is too low! Minimum: {self.minimum}")
if self.maximum is not None and value > self.maximum:
raise ValueError(f"Value {value} is too high! Maximum: {self.maximum}")
instance._attr = value
def __delete__(self, instance):
del instance._attr
class Test:
attr = RangeValue(0, 100)
t = Test()
t.attr = 50
print(t.attr)
输出:
50
当属性值处于给定范围之外时,赋值将会抛出异常:
class Test:
attr = RangeValue(0, 100)
t = Test()
t.attr = 150
输出:
ValueError: Value 150 is too high! Maximum: 100
计算属性
描述符可以用于实现一些高级属性的逻辑。例如,计算一个矩形的面积和周长:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height
@property
def perimeter(self):
return 2 * (self.width + self.height)
class Area:
def __get__(self, instance, owner):
return instance.width * instance.height
class Perimeter:
def __get__(self, instance, owner):
return 2 * (instance.width + instance.height)
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
area = Area()
perimeter = Perimeter()
r = Rectangle(3, 4)
print(r.area)
print(r.perimeter)
输出:
12
14
总结
Python描述符是实现高级属性逻辑的重要机制。通过描述符,我们可以实现对属性访问、赋值和删除的控制,以及实现一些高级属性的逻辑。在实际开发中,描述符可以应用于多种场景,例如,实现访问控制、属性校验和计算属性等。