h5如何做多頁面網(wǎng)站愛站查詢
文章目錄
- 類型:
- 數(shù)據(jù)描述符:
- 方法描述符:
- 描述符的要包括以下幾點:
- 方法描述符
- 實現(xiàn)緩存
描述符(Descriptor)
是 Python 中一個非常強大的特性,它允許我們自定義屬性的訪問行為。使用描述符,我們可以創(chuàng)建一些特殊的屬性,在訪問這些屬性時執(zhí)行自定義的邏輯,如數(shù)據(jù)驗證、屬性計算等。
類型:
**數(shù)據(jù)描述符:**用于修改屬性的訪問和修改行為。
**方法描述符:**用于修改方法的行為。
數(shù)據(jù)描述符:
**get:**在屬性被訪問時被調(diào)用。
**set:**在屬性被設置時被調(diào)用。
**delete:**在屬性被刪除時被調(diào)用。
方法描述符:
**call:**在方法被調(diào)用時被調(diào)用。
下面我們來看一個具體的例子:
class MyDescriptor:def __init__(self, initial_value=None):self._value = initial_valuedef __get__(self, instance, owner):print(f"Getting value: {self._value}")return self._valuedef __set__(self, instance, value):print(f"Setting 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
類,它實現(xiàn)了三個描述符協(xié)議方法:__get__
、__set__
和 __delete__
。這些方法分別在訪問、設置和刪除屬性時被調(diào)用。
在 MyClass
中,我們定義了一個 my_attr
屬性,它使用 MyDescriptor
作為描述符。當我們訪問、設置或刪除 obj.my_attr
時,相應的描述符方法會被調(diào)用,并執(zhí)行我們自定義的邏輯。
描述符的要包括以下幾點:
- 數(shù)據(jù)驗證: 可以在
__set__
方法中添加數(shù)據(jù)驗證邏輯,確保屬性值符合預期。 - 屬性計算: 在
__get__
方法中實現(xiàn)動態(tài)計算屬性值的邏輯。 - 屬性緩存: 使用描述符可以實現(xiàn)屬性值的緩存,提高訪問性能。
- 懶加載: 描述符可以用于實現(xiàn)懶加載,即在第一次訪問屬性時才計算或加載屬性值。
- 屬性權(quán)限控制: 可以使用描述符實現(xiàn)只讀、只寫或讀寫屬性。
- 屬性依賴管理: 描述符可以用于管理屬性之間的依賴關(guān)系,確保屬性值的一致性。
下面是一個的代碼示例,實現(xiàn)了一個帶有數(shù)據(jù)驗證和屬性緩存的描述符:
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 = age@CachedPropertydef full_name(self):print("Calculating full name...")return f"{self.name} Smith"@propertydef age(self):return self._age@age.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
的區(qū)別如下:
-
self
:self
代表的是Person
類本身的實例,也就是Person
類的一個對象。- 在
__get__
方法中,self
指向的是Person
類的age
屬性本身,而不是某個特定的Person
對象。
-
instance
:instance
代表的是正在訪問age
屬性的Person
對象實例。- 在
__get__
方法中,instance
指向的是調(diào)用age
屬性的具體Person
對象,比如上例中的person
對象。
簡單來說:
self
指向的是屬性本身(即age
屬性),而instance
指向的是正在訪問該屬性的對象實例。self
是屬性級別的,而instance
是對象級別的。owner
是屬性的類對象
這個區(qū)別很重要,因為在 __get__
方法中,我們需要根據(jù)具體的 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) # 結(jié)果為30
解釋:
__call__
方法描述符允許將Calculator
類本身作為函數(shù)調(diào)用。- 在
__call__
方法中,self
參數(shù)表示Calculator
對象,a
和b
參數(shù)表示方法參數(shù)。 - 方法返回
Calculator
對象本身,以便可以繼續(xù)使用其方法。
優(yōu)點:
- 簡化了方法調(diào)用過程。
- 允許將類作為函數(shù)使用。
- 提高了代碼可讀性。
注意事項:
__call__
方法描述符僅適用于類。- 如果
__call__
方法描述符不正確定義,會導致錯誤。
實現(xiàn)緩存
在這個例子中,當我們嘗試訪問一個實例對象的屬性時,__get__
方法會被調(diào)用。如果實例對象沒有該屬性的緩存值,它會調(diào)用 self.func(instance)
來計算屬性值,并將其緩存在實例對象上。
這種技術(shù)被稱為"惰性計算"(lazy evaluation),它可以提高性能,因為屬性值只有在第一次被訪問時才會計算。之后,后續(xù)的訪問都會直接返回緩存的值,而不需要再次計算。
下面是一個更具體的例子:
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 = age@LazyPropertydef full_name(self):print("Calculating full name...")return f"{self.name} Smith"person = Person("Alice", 30)
print(person.full_name) # 輸出: "Calculating full name..." 和 "Alice Smith"
print(person.full_name) # 輸出: "Alice Smith"
在這個例子中,我們定義了一個 LazyProperty
描述符類,它在第一次訪問 full_name
屬性時計算并緩存該值。后續(xù)訪問都會直接返回緩存的值,而不需要再次計算。
總的來說,self.func(instance)
是描述符對象用來計算屬性值的方法調(diào)用。通過使用描述符,我們可以自定義屬性的訪問行為,實現(xiàn)惰性計算等優(yōu)化手段,提高代碼的性能和可維護性。