Python decorators on class members fail when decorator mechanism is a class

2024/10/4 23:31:57

When creating decorators for use on class methods, I'm having trouble when the decorator mechanism is a class rather than a function/closure. When the class form is used, my decorator doesn't get treated as a bound method.

Generally I prefer to use the function form for decorators but in this case I have to use an existing class to implement what I need.

This seems as though it might be related to python-decorator-makes-function-forget-that-it-belongs-to-a-class but why does it work just fine for the function form?

Here is the simplest example I could make to show all goings on. Sorry about the amount of code:

def decorator1(dec_param):def decorator(function):print 'decorator1 decoratoring:', functiondef wrapper(*args):print 'wrapper(%s) dec_param=%s' % (args, dec_param)function(*args)return wrapperreturn decoratorclass WrapperClass(object):def __init__(self, function, dec_param):print 'WrapperClass.__init__ function=%s dec_param=%s' % (function, dec_param)self.function = functionself.dec_param = dec_paramdef __call__(self, *args):print 'WrapperClass.__call__(%s, %s) dec_param=%s' % (self, args, self.dec_param)self.function(*args)def decorator2(dec_param):def decorator(function):print 'decorator2 decoratoring:', functionreturn WrapperClass(function, dec_param)return decoratorclass Test(object):@decorator1(dec_param=123)def member1(self, value=1):print 'Test.member1(%s, %s)' % (self, value)@decorator2(dec_param=456)def member2(self, value=2):print 'Test.member2(%s, %s)' % (self, value)@decorator1(dec_param=123)
def free1(value=1):print 'free1(%s)' % (value)@decorator2(dec_param=456)
def free2(value=2):print 'free2(%s)' % (value)test = Test()
print '\n====member1===='
test.member1(11)print '\n====member2===='
test.member2(22)print '\n====free1===='
free1(11)print '\n====free2===='
free2(22)

Output:

decorator1 decoratoring: <function member1 at 0x3aba30>
decorator2 decoratoring: <function member2 at 0x3ab8b0>
WrapperClass.__init__ function=<function member2 at 0x3ab8b0> dec_param=456
decorator1 decoratoring: <function free1 at 0x3ab9f0>
decorator2 decoratoring: <function free2 at 0x3ab970>
WrapperClass.__init__ function=<function free2 at 0x3ab970> dec_param=456====member1====
wrapper((<__main__.Test object at 0x3af5f0>, 11)) dec_param=123
Test.member1(<__main__.Test object at 0x3af5f0>, 11)====member2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af590>, (22,)) dec_param=456
Test.member2(22, 2)        <<<- Badness HERE!====free1====
wrapper((11,)) dec_param=123
free1(11)====free2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af630>, (22,)) dec_param=456
free2(22)
Answer

Your WrapperClass needs to be a descriptor (just like a function is!), i.e., supply appropriate special methods __get__ and __set__. This how-to guide teaches all you need to know about that!-)

https://en.xdnf.cn/q/70556.html

Related Q&A

Why does comparison of a numpy array with a list consume so much memory?

This bit stung me recently. I solved it by removing all comparisons of numpy arrays with lists from the code. But why does the garbage collector miss to collect it?Run this and watch it eat your memor…

StringIO portability between python2 and python3 when capturing stdout

I have written a python package which I have managed to make fully compatible with both python 2.7 and python 3.4, with one exception that is stumping me so far. The package includes a command line scr…

How to redirect data to a getpass like password input?

Im wring a python script for running some command. Some of those commands require user to input password, I did try to input data in their stdin, but it doesnt work, here is two simple python program…

How to grab one random item from a database in Django/postgreSQL?

So i got the database.objects.all() and database.objects.get(name) but how would i got about getting one random item from the database. Im having trouble trying to figure out how to get it ot select on…

Pyspark Dataframe pivot and groupby count

I am working on a pyspark dataframe which looks like belowid category1 A1 A1 B2 B2 A3 B3 B3 BI want to unstack the category column and count their occurrences. So, the result I want is shown belowid A …

Create an excel file from BytesIO using python

I am using pandas library to store excel into bytesIO memory. Later, I am storing this bytesIO object into SQL Server as below-df = pandas.DataFrame(data1, columns=[col1, col2, col3])output = BytesIO()…

python send csv data to spark streaming

I would like to try and load a csv data in python and stream each row spark via SPark Streaming.Im pretty new to network stuff. Im not exactly if Im supposed to create a server python script that once …

Python string representation of binary data

Im trying to understand the way Python displays strings representing binary data.Heres an example using os.urandomIn [1]: random_bytes = os.urandom(4)In [2]: random_bytes Out[2]: \xfd\xa9\xbe\x87In [3]…

Combining Spark Streaming + MLlib

Ive tried to use a Random Forest model in order to predict a stream of examples, but it appears that I cannot use that model to classify the examples. Here is the code used in pyspark:sc = SparkContext…

How to select dataframe rows according to multi-(other column)-condition on columnar groups?

Copy the following dataframe to your clipboard:textId score textInfo 0 name1 1.0 text_stuff 1 name1 2.0 different_text_stuff 2 name1 2.0 text_stuff …