簡體   English   中英

Python - 將類作為參數傳遞給該類中方法的裝飾器?

[英]Python - Pass class as argument to decorator of method within that class?

我正在尋找執行以下操作:

class A(object):
    def first_method(self):
        print "I'm the first method!"    

    @some_decorator(A.first_method)
    def second_method(self):
        print "I'm the second method!"

但是我遇到了在解析裝飾器時A本身未定義的問題。 有什么辦法可以讓我在裝飾器中引用A嗎? 或者,如果我只是通過裝飾器綁定方法first_method是否可以恢復first_method屬於A

在 python 3 中,你可以只說@some_decorator(first_method) ,它會起作用,因為所有方法都是作為容器的類中的普通函數。

在python 2中,有一個復雜的綁定和未綁定、實例、類和靜態方法系統。 因此,您無法在類定義中訪問first_method (直到類完全形成)。

一個小的解決方法是將該類拆分為兩個類:

class BaseA(object):
    def first_method(self):
        print "I'm the first method!"    

class A(BaseA):
    @some_decorator(BaseA.first_method)
    def second_method(self):
        print "I'm the second method!"

不是所有情況的最佳解決方案,但會起作用。


另外,請記住,在這兩種情況下(py2 和 py3),裝飾器將引用此處聲明的first_method 如果任何后代類重新定義了該方法,則裝飾器中將不會使用新方法; 只有父級會被使用。

可能,您根本不應該引用first_method 相反,只需在裝飾器的包裝器中接受self / cls第一個位置參數,並在那里使用self.first_method / cls.first_method

import functools

def some_decorator(fn):
    @functools.wraps(fn)
    def wrapper(self, *args, **kwargs):
        first_method = self.first_method
        first_method()
        return fn(self, *args, **kwargs)
    return wrapper

class A(object):
    def first_method(self):
        print "I'm the first method of A!"    

    @some_decorator
    def second_method(self):
        print "I'm the second method!"


class B(A):
    def first_method(self):
        print "I'm the first method of B!"    


A().second_method()
# I'm the first method of A!
# I'm the second method!

B().second_method()
# I'm the first method of B!
# I'm the second method!

如果要使該方法可配置:

def some_decorator(method_name):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(self, *args, **kwargs):
            first_method = getattr(self, method_name)
            first_method()
            return fn(self, *args, **kwargs)
        return wrapper
    return decorator


class A(object):
    def first_method(self):
        print "I'm the first method of A!"    

    @some_decorator('first_method')
    def second_method(self):
        print "I'm the second method!"

class B(A):
    def first_method(self):
        print "I'm the first method of B!"    

您可以將裝飾器用作經典函數(不帶 @):

def some_decorator(arg):
    # ...
    pass


class A(object):
    def first_method(self):
        print("I'm the first method!")

    def second_method(self):
        print("I'm the second method!")


A.second_method = some_decorator(A.first_method)(A.second_method)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM