Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 可以同时接受init参数和call参数的Decorator?_Python_Design Patterns_Decorator - Fatal编程技术网

Python 可以同时接受init参数和call参数的Decorator?

Python 可以同时接受init参数和call参数的Decorator?,python,design-patterns,decorator,Python,Design Patterns,Decorator,是否可以创建一个decorator,该decorator可以使用一组参数\uuuu init\uuu'd,然后使用其他参数调用方法 例如: from foo import MyDecorator bar = MyDecorator(debug=True) @bar.myfunc(a=100) def spam(): pass @bar.myotherfunc(x=False) def eggs(): pass 如果这是可能的,您能提供一个工作示例吗?当然,decorato

是否可以创建一个decorator,该decorator可以使用一组参数
\uuuu init\uuu
'd,然后使用其他参数调用方法

例如:

from foo import MyDecorator

bar = MyDecorator(debug=True)

@bar.myfunc(a=100)
def spam():
    pass

@bar.myotherfunc(x=False)
def eggs():
    pass

如果这是可能的,您能提供一个工作示例吗?

当然,decorator只是一个接受函数并返回函数的函数。没有理由认为函数不能是实例方法(或者,如果有参数,则不能由实例方法返回)。这里有一个非常简单的例子(因为我不确定你到底想用这个做什么):

就像我说的,我想不出一个这样的用例。但我肯定他们就在那里。

情况是这样的
@property
装饰函数,并将其替换为具有getter、setter和deleter函数(也是装饰器)的对象


这比OP的示例稍微复杂一些,因为有两个装饰级别,但原理是相同的。

您需要另一个级别的包装,例如使用闭包:

import functools

def say_when_called(what_to_say):
    def decorator(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kw):
            print what_to_say
            return fn(*args, **kw)
        return wrapper
    return decorator

@say_when_called("spam")
def my_func(v):
    print v

my_func("eggs")
输出:

spam
eggs
spam
eggs
(见附件)

请注意,我在这里使用了
functools.wrapps
,使修饰后的函数看起来像原来的函数。这在功能上不是必需的,但在代码读取函数的
\uuuuu name\uuuuuu
\uuuu doc\uuuuu
属性的情况下,这是一件很好的事情

一个基于类的示例:

class SayWhenCalledWrapper(object):

    def __init__(self, fn, what_to_say):
        self.fn = fn
        self.what_to_say = what_to_say

    def __call__(self, *args, **kw):
        print self.what_to_say
        return self.fn(*args, **kw)


class SayWhenCalled(object):

    def __init__(self, what_to_say):
        self.what_to_say = what_to_say

    def __call__(self, fn):
        return SayWhenCalledWrapper(fn, self.what_to_say)


@SayWhenCalled("spam")
def my_func(v):
    print v

my_func("eggs")
输出:

spam
eggs
spam
eggs

(见)huin的回答很好。他的两个选项仅在定义装饰函数时执行装饰器代码(这不是批评,因为这通常正是您想要的)。这是他基于类的方法的扩展,每次调用函数时也会执行一些代码。例如,当您使用decorator来确保线程安全时,就是这样做的

class MyInnerDecorator:
    def __init__( self, outer_decorator, *args, **kwargs ):
        self._outerDecorator = outer_decorator
        self._args = args
        self._kwargs = kwargs

    def __call__( self, f ):
        print "Decorating function\n"
        self._f = f
        return self.wrap


    def wrap( self, *args, **kwargs ):
        print "Calling decorated function"
        print "Debug is ",                          self._outerDecorator._debug
        print "Positional args to decorator: ",     self._args
        print "Keyword args to decorator: ",        self._kwargs
        print "Positional args to function call: ", args
        print "Keyword args to function call: ",    kwargs
        return self._f( *args, **kwargs )
        print "\n"



class MyDecorator:
    def __init__( self, debug ):
        self._debug = debug

    def myFunc( self, *args, **kwargs ):
        return MyInnerDecorator( self, "Wrapped by myFunc", *args, **kwargs )

    def myOtherFunc( self, *args, **kwargs ):
        return MyInnerDecorator( self, "Wrapped by myOtherFunc", *args, **kwargs )


bar = MyDecorator( debug=True )
@bar.myFunc( a=100 )
def spam( *args, **kwargs ):
    print "\nIn spam\n"

@bar.myOtherFunc( x=False )
def eggs( *args, **kwargs ):
    print "\nIn eggs\n"

spam( "penguin" )

eggs( "lumberjack" )
哪个输出:

Decorating function

Decorating function

Calling decorated function
Debug is  True
Positional args to decorator:  ('Wrapped by myFunc',)
Keyword args to decorator:  {'a': 100}
Positional args to function call:  ('penguin',)
Keyword args to function call:  {}

In spam

Calling decorated function
Debug is  True
Positional args to decorator:  ('Wrapped by myOtherFunc',)
Keyword args to decorator:  {'x': False}
Positional args to function call:  ('lumberjack',)
Keyword args to function call:  {}

In eggs

我可以问一下你想要完成什么吗?我真的很好奇。第一个抱怨我暗示函数和实例方法是一样的东西的人得到了一个馅饼在脸上;-)好吧,装饰器必须是一个
可调用的
,它接受一个
可调用的
并返回一些东西-但通常这些东西也应该是可调用的,否则你会让任何读者感到困惑。我有馅饼吗?;-)