[英]Set the property of a class using decorators on a class method in python
我有一個ABC
類,里面有一個功能someFunction
。
我不想弄亂someFunction
的代碼,因此用@MyDecorator
包裝它。 當我調用someFunction
時,該MyDecorator
如何修改ABC
類的屬性?
class ABC(object):
def __init__(self):
self.someProperty = "Initial value"
@MyDecorator
def someFunction(self):
print "Hello world"
class MyDecorator(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
# ...???
return self.func(*args, **kwargs)
abc = ABC()
abc.someFunction() # When calling someFunction(), abc.someProperty would be updated
你可以試試:
class MyDecorator(object):
def __init__(self, func):
self.func = func
def __call__(self, instance, *args, **kwargs):
instance.someProperty = "New value"
return self.func(instance, *args, **kwargs)
def __get__(self, instance, owner):
if instance is None:
return self
return self.__call__.__class__(self, instance)
class ABC(object):
def __init__(self):
self.someProperty = "Initial value"
@MyDecorator
def someFunction(self):
print("Hello world")
MyDecorator
現在是一個描述符,因為它實現了__get__
。
通過某個類或該類的實例訪問MyDecorator
的任何實例的屬性時,將調用__get__
。
__get__
將在參數instance
接收該所有者對象的instance
,從那里我們可以返回一個新的instancemethod instancemethod
,該instance
隱式接收該instance
:
>>> abc.someFunction.__class__
<type 'instancemethod'>
>>> abc.someFunction.__class__.__doc__
'instancemethod(function, instance, class)\n\nCreate an instance method object.'
>>>
它需要一個function
,基本上任何可調用的對象將工作,因為MyDecorator
是一流的, __call__
將修改自己的self
。
實際上:
>>> abc = ABC()
>>> abc.someProperty
'Initial value'
>>> abc.someFunction()
Hello world
>>> abc.someProperty
'New value'
>>>
請注意,在Python 2.X中, MyDecorator
必須是繼承object
的新類,否則將不起作用。
您需要在文件中定義MyDecorator的位置早於使用它的位置,否則會收到“ NameError:未定義名稱'MyDecorator'的信息”。
當我說“裝飾器應該返回一個函數”時,我錯了。 在我的示例中,這適用於用作裝飾器的函數。 但是,當使用一個類時,它不必返回這樣的函數。 它返回該類中的一個對象。 如果將“類MyDecorator”命名為“類MyModifiedFunction”,則可能會減少混淆,因為該類的元素用作修飾函數。
通常,裝飾器返回的函數將調用原始函數。 你的不是。 如果您要完全替換someFunction而不是僅僅對其進行修改,則不必這樣做。
您無需將MyDecorator設置為類。 您可以使其功能。 這是一個例子:
def MyDecorator(original_function):
def replacement_function(*args, **kwargs):
args[0].some_property = some_new_value
return(original_function(*args, **kwargs))
return(replacement_function)
在代碼的前半部分之后定義ABC
類。
請注意,當它說return(original_function(*args, **kwargs))
它正在運行原始函數並返回原始函數返回的任何內容。 如果原始函數返回了一個對象,它將返回該對象。 但是,當它說return(replacement_function)
它所做的事情卻大不相同:當時它沒有運行替換函數; 它只是將函數作為返回值返回。 裝飾器必須返回一個函數。
(@dano:好點。我認為是固定的。)
這是上述建議的更完整形式:
def MyDecorator(original_function):
def replacement_function(*args, **kwargs):
args[0].some_property = 'Modified value'
return(original_function(*args, **kwargs))
return(replacement_function)
class ABC(object):
def __init__(self):
self.some_property = "Initial value"
@MyDecorator
def some_function(self):
print "Hello world"
abc = ABC()
abc.some_function() # When calling some_function(), abc.some_property wou
ld更新
print "some property is", abc.some_property
我運行了它,它起作用了; 它打印
Hello world
some property is Modified value
因此,這可以驗證它確實修改了abc中的some_property。 它以args[0].some_property
的形式訪問,因為調用修飾的函數(作為對象方法)時, self
作為第一個參數傳遞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.