Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.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 使用getattr将Get方法包装在描述符中_Python_Descriptor - Fatal编程技术网

Python 使用getattr将Get方法包装在描述符中

Python 使用getattr将Get方法包装在描述符中,python,descriptor,Python,Descriptor,我有以下描述符,它在调用一个用@saveconfig注释的方法后将配置保存在我的类中: class saveconfig(object): def __init__(self, f): self.f = f def __get__(self, instance, owner): def wrapper(*args): self.f(instance, *args) instance.cfg.writ

我有以下描述符,它在调用一个用
@saveconfig
注释的方法后将配置保存在我的类中:

class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, instance, owner):
        def wrapper(*args):
            self.f(instance, *args)
            instance.cfg.write()
            instance.paramcfg.write()
        return wrapper
它是这样使用的:

class pbtools():
    @saveconfig
    def getip(self, ip):
        (...)
pbtools getip 192.168.178.123 #-> calls getip with parameter 192.168.178.123
class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, instance, owner):
        def wrapper(*args):
            self.f(instance, *args)
            instance.cfg.write()
            instance.paramcfg.write()

        wrapper.func = self.f    # Create a new attribute and assign it to the wrapped func.
        return wrapper
import sys
cmd = sys.argv[1]
params = sys.argv[2:]

pbt = pbtools()

func = getattr(pbt, cmd)
func(*params)
它很好用。现在,我想通过使用getattr获得修饰的方法。但由于该方法是由描述符包装的,因此我只得到
wrapper

pbt = pbtools()
# results in "<function wrapper at 0x23cced8>:"
method = getattr(pbt, "getip")

因为我无法获得原始方法,所以我不知道需要映射多少参数。我有几个这样修饰的方法,因为我想把保存配置的横切关注点从pbtools类的方法中移开

首先,我对我的错误表示歉意,因为您最后的代码将无法像您一样工作(您的方法不再被修饰),因为要理解decorator,您必须看到以下内容:

class pbtools():
    @saveconfig
    def getip():
        (...)
相当于:

class pbtools():

    def getip():
        (...)

    getip = saveconfig(getip)
在您最新的案例中,
saveconfig
return
self.f
,它在我们的代码中等于
getip
,因此在本例中,此代码:

getip = saveconfig(getip)
相当于:

 getip = getip
所以基本上它什么也不做

可以通过将包装函数保存在包装函数中来解决此问题,如下所示:

class pbtools():
    @saveconfig
    def getip(self, ip):
        (...)
pbtools getip 192.168.178.123 #-> calls getip with parameter 192.168.178.123
class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, instance, owner):
        def wrapper(*args):
            self.f(instance, *args)
            instance.cfg.write()
            instance.paramcfg.write()

        wrapper.func = self.f    # Create a new attribute and assign it to the wrapped func.
        return wrapper
import sys
cmd = sys.argv[1]
params = sys.argv[2:]

pbt = pbtools()

func = getattr(pbt, cmd)
func(*params)
现在你可以:

class pbtools():
    @saveconfig
    def getip():
        print "hi"

pbt = pbtools()
method = getattr(pbt, "getip")
print method.func
# <function getip at 0x2363410>
method.func()
# hi
class pbtools():
@保存配置
def getip():
打印“嗨”
pbt=pbtools()
方法=getattr(pbt,“getip”)
print method.func
# 
方法。func()
#嗨

希望这能有所帮助:)

我还不能100%肯定我完全理解你的问题。您说“由于我无法获得原始方法,我不知道它必须映射多少个参数”,但您不需要访问原始方法才能通过可变数量的参数进行调用(因为decorator具有
*args
)。您可以这样做:

class pbtools():
    @saveconfig
    def getip(self, ip):
        (...)
pbtools getip 192.168.178.123 #-> calls getip with parameter 192.168.178.123
class saveconfig(object):
    def __init__(self, f):
        self.f = f

    def __get__(self, instance, owner):
        def wrapper(*args):
            self.f(instance, *args)
            instance.cfg.write()
            instance.paramcfg.write()

        wrapper.func = self.f    # Create a new attribute and assign it to the wrapped func.
        return wrapper
import sys
cmd = sys.argv[1]
params = sys.argv[2:]

pbt = pbtools()

func = getattr(pbt, cmd)
func(*params)
你也可以简化你的装饰。它实际上并不需要
\uuuuu获取\uuuuu
机制

import functools

def saveconfig(f):
    @functools.wraps(f)
    def wrapper(self, *args):
        f(self, *args)
        self.cfg.write()
        self.paramcfg.write()
    return wrapper

functools.wrapps
是一个帮助器装饰器,它使包装器模仿原始函数(即复制函数名、docstring等)。这将使调试变得更容易,因为您将知道异常来自何处等。

关于:
method=getattr(pbt,“getip”)。f
?不,该方法不能像那样访问。我正在获取AttributeError:“function”对象没有属性“f”,为什么不使用?装饰器的全部目的是用包装器替换方法,因此您无法通过
getattr
获取原始方法,同时仍保留装饰器的保存功能。您需要原始方法做什么?如果您可以使用函数作为装饰器而不是类,您可以使用functools.wrapps as@KennyTM提到它会更好,但希望我的答案能给您一些帮助:)谢谢,很好的解决方案。我重新编译了我的代码,现在它可以工作了。之前,我使用
inspect
检查要调用的方法的参数。但inspect只提供包装器的参数数。我现在删除了inspect内容,并尝试调用该方法,该方法被包装在trycatch中。