达州住房和城乡建设厅网站,wordpress会员中心插件,网站建设中申请备案,廊坊做网站外包文章目录 类型#xff1a;数据描述符#xff1a;方法描述符#xff1a;描述符的要包括以下几点:方法描述符实现缓存 描述符(Descriptor)是 Python 中一个非常强大的特性,它允许我们自定义属性的访问行为。使用描述符,我们可以创建一些特殊的属性,在访问这些属性时执行自定义… 文章目录 类型数据描述符方法描述符描述符的要包括以下几点:方法描述符实现缓存 描述符(Descriptor)是 Python 中一个非常强大的特性,它允许我们自定义属性的访问行为。使用描述符,我们可以创建一些特殊的属性,在访问这些属性时执行自定义的逻辑,如数据验证、属性计算等。 类型
**数据描述符**用于修改属性的访问和修改行为。 **方法描述符**用于修改方法的行为。
数据描述符
**get**在属性被访问时被调用。 **set**在属性被设置时被调用。 **delete**在属性被删除时被调用。
方法描述符
**call**在方法被调用时被调用。
下面我们来看一个具体的例子:
class MyDescriptor:def __init__(self, initial_valueNone):self._value initial_valuedef __get__(self, instance, owner):print(fGetting value: {self._value})return self._valuedef __set__(self, instance, value):print(fSetting value to: {value})self._value valuedef __delete__(self, instance):print(Deleting value)del self._valueclass MyClass:my_attr MyDescriptor(42)obj MyClass()
print(obj.my_attr) # Output: Getting value: 42
obj.my_attr 100 # Output: Setting value to: 100
del obj.my_attr # Output: Deleting value在这个例子中,我们定义了一个 MyDescriptor 类,它实现了三个描述符协议方法:__get__、__set__ 和 __delete__。这些方法分别在访问、设置和删除属性时被调用。
在 MyClass 中,我们定义了一个 my_attr 属性,它使用 MyDescriptor 作为描述符。当我们访问、设置或删除 obj.my_attr 时,相应的描述符方法会被调用,并执行我们自定义的逻辑。
描述符的要包括以下几点:
数据验证: 可以在 __set__ 方法中添加数据验证逻辑,确保属性值符合预期。属性计算: 在 __get__ 方法中实现动态计算属性值的逻辑。属性缓存: 使用描述符可以实现属性值的缓存,提高访问性能。懒加载: 描述符可以用于实现懒加载,即在第一次访问属性时才计算或加载属性值。属性权限控制: 可以使用描述符实现只读、只写或读写属性。属性依赖管理: 描述符可以用于管理属性之间的依赖关系,确保属性值的一致性。
下面是一个的代码示例,实现了一个带有数据验证和属性缓存的描述符:
class CachedProperty:def __init__(self, getter):self.getter getterself._cache {}def __get__(self, instance, owner):if instance is None:return selfif instance not in self._cache:self._cache[instance] self.getter(instance)return self._cache[instance]def __set__(self, instance, value):self._cache[instance] valuedef __delete__(self, instance):if instance in self._cache:del self._cache[instance]class Person:def __init__(self, name, age):self.name nameself.age ageCachedPropertydef full_name(self):print(Calculating full name...)return f{self.name} Smithpropertydef age(self):return self._ageage.setterdef age(self, value):if value 0:raise ValueError(Age cannot be negative)self._age valuep Person(John, 30)
print(p.full_name) # Output: Calculating full name... John Smith
print(p.full_name) # Output: John Smith (from cache)p.age 40
print(p.age) # Output: 40p.age -10 # Raises ValueError: Age cannot be negative在这个场景下,self 和 instance 的区别如下: self: self 代表的是 Person 类本身的实例,也就是 Person 类的一个对象。在 __get__ 方法中,self 指向的是 Person 类的 age 属性本身,而不是某个特定的 Person 对象。 instance: instance 代表的是正在访问 age 属性的 Person 对象实例。在 __get__ 方法中,instance 指向的是调用 age 属性的具体 Person 对象,比如上例中的 person 对象。
简单来说:
self 指向的是属性本身(即 age 属性),而 instance 指向的是正在访问该属性的对象实例。self 是属性级别的,而 instance 是对象级别的。owner 是属性的类对象
这个区别很重要,因为在 __get__ 方法中,我们需要根据具体的 Person 对象实例(instance)来计算年龄,而不是直接使用 self(即 age 属性本身)。
方法描述符
class Calculator:def __init__(self):self.num1 0self.num2 0def __call__(self, a, b):self.num1 aself.num2 breturn selfdef add(self):return self.num1 self.num2calc Calculator()
result calc(10, 20)
print(result) # 结果为30解释
__call__ 方法描述符允许将 Calculator 类本身作为函数调用。在 __call__ 方法中self 参数表示 Calculator 对象a 和 b 参数表示方法参数。方法返回 Calculator 对象本身以便可以继续使用其方法。
优点
简化了方法调用过程。允许将类作为函数使用。提高了代码可读性。
注意事项
__call__ 方法描述符仅适用于类。如果 __call__ 方法描述符不正确定义会导致错误。
实现缓存 在这个例子中,当我们尝试访问一个实例对象的属性时,__get__ 方法会被调用。如果实例对象没有该属性的缓存值,它会调用 self.func(instance) 来计算属性值,并将其缓存在实例对象上。
这种技术被称为惰性计算(lazy evaluation),它可以提高性能,因为属性值只有在第一次被访问时才会计算。之后,后续的访问都会直接返回缓存的值,而不需要再次计算。
下面是一个更具体的例子:
class LazyProperty:def __init__(self, func):self.func funcself.cache_name f_{func.__name__}def __get__(self, instance, owner):if instance is None:return selfif not hasattr(instance, self.cache_name):value self.func(instance)setattr(instance, self.cache_name, value)return getattr(instance, self.cache_name)class Person:def __init__(self, name, age):self.name nameself.age ageLazyPropertydef full_name(self):print(Calculating full name...)return f{self.name} Smithperson Person(Alice, 30)
print(person.full_name) # 输出: Calculating full name... 和 Alice Smith
print(person.full_name) # 输出: Alice Smith在这个例子中,我们定义了一个 LazyProperty 描述符类,它在第一次访问 full_name 属性时计算并缓存该值。后续访问都会直接返回缓存的值,而不需要再次计算。
总的来说,self.func(instance) 是描述符对象用来计算属性值的方法调用。通过使用描述符,我们可以自定义属性的访问行为,实现惰性计算等优化手段,提高代码的性能和可维护性。