[英]Using Python's __get__ descriptor for non-class attributes
使用__get__
描述符我想實現這樣的目標:
class Wrapper:
def __init__(self, wrapped_value):
self._wrapped_value = wrapped_value
def __get__(self, instance, owner):
return self._wrapped_value
wrapper = Wrapper('foo')
assert type(wrapper) == type('foo')
事實證明,只有當Wrapper
實例是某個其他類的類屬性時,才會調用__get__
描述符,當Wrapper
實例是獨立對象(未綁定到任何類屬性)時,它不會被調用。
有沒有辦法讓__get__
描述符在非類屬性中工作?
主要目標是實現包裝器,當使用它時就像它包裝的值一樣(我知道乍一看這聽起來沒什么用,但在某些用例中這會有所幫助)。 那么也許有其他方法可以在不使用__get__
描述符的情況下實現這一__get__
?
如果您希望您的 Wrapper 類控制對包裝類屬性的訪問,您可以使用__getattr__
魔術方法。
假設我們有一個類Foo
:
class Foo(object):
def bar(self):
return 'bar'
def baz(self):
return 'baz'
假設我們正在與一些我們無法控制的代碼進行交互,這些代碼要求Foo.bar()
的輸出為大寫,並且我們不想在我們的代碼中顯式調用.upper()
。
我們可以創建一個包裝類來攔截對Foo.bar()
調用,但透明地允許訪問Foo
的其他方法(這本質上是適配器模式)。
class Wrapper(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattr__(self, name):
# If 'name' isn't an attribute of this class,
# get it from the wrapped instance.
return getattr(self._wrapped, name)
def bar(self):
# Intercept calls to the wrapped instance's bar() method.
return self._wrapped.bar().upper()
>>> wrapper = Wrapper(Foo())
>>> print wrapper.baz()
baz
>>> print wrapper.bar()
BAR
這個 Wrapper 類不會被type
或isinstance
檢查報告為Foo
,但否則它可以代替Foo
,只要調用代碼依賴於鴨子類型而不是(非pythonic)顯式類型檢查。
攔截諸如__str__
魔術方法必須顯式完成。 這是因為這些方法總是直接在實例的類上查找,所以__getattr__
和__getattribute__
被繞過。
因此,要覆蓋Foo.__str__
您需要執行以下操作:
class Foo(object):
...
def __str__(self):
return 'I am a Foo'
class Wrapper(object):
...
def __str__(self):
return str(self._wrapped)
>>> wrapper = Wrapper(Foo())
>>> print wrapper
I am a Foo
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.