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
returnself.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中。