使用 getattr 获取包含在描述符中的方法
我有以下描述符,它在调用用 @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):
(...)
它工作正常。现在我想通过使用 getattr 来获取装饰方法。但由于该方法是由描述符包装的,因此我只能得到 wrapper
结果:
pbt = pbtools()
# results in "<function wrapper at 0x23cced8>:"
method = getattr(pbt, "getip")
How can i access thewrapper method getip
with getattr, to be able to call it by它的名字? (当然我无法直接访问该方法,否则我不必这样做)。
附加说明:
该脚本是从命令行调用的。我必须将命令行参数(字符串)映射到具有相同名称的方法才能调用它。此外,我必须将任何其他参数从comamndline映射到该方法的参数,如下所示:
pbtools getip 192.168.178.123 #-> calls getip with parameter 192.168.178.123
由于我无法获取原始方法,所以我不知道它必须映射它们多少个参数。我有几个像这样装饰的方法,因为我想将保存配置的横切关注点移出 pbtools 类中的方法。
I have the following descriptor, which saves the configuration inside my class after a method which is annotated with @saveconfig
is called:
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
It's used like this:
class pbtools():
@saveconfig
def getip(self, ip):
(...)
It works fine. Now i want to get the decorated method by using getattr. But since the method is wrapped by the descriptor, i only get wrapper
as a result:
pbt = pbtools()
# results in "<function wrapper at 0x23cced8>:"
method = getattr(pbt, "getip")
How can i access the wrapped method getip
with getattr, to be able to call it by it's name? (of course i cannot access the method directly otherwise i would not have to do that).
Additional explanation:
The script is called from commandline. I have to map a command line parameter (string) to a method with the same name to invoke it. Furthermore, i have to map any additional parameters from the comamndline to parameters of the method, like this:
pbtools getip 192.168.178.123 #-> calls getip with parameter 192.168.178.123
Since i cannot get the original method, i don't know how many parameters it has to map them. I have several methods that are decorated like that, because i want to move the cross cutting concern of saving the config out of the methods in the pbtools-class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我仍然不能百分百确定我完全理解你的问题。你说“因为我无法获得原始方法,所以我不知道它有多少参数来映射它们”,但是你不需要访问原始方法来通过可变数量的参数调用(因为装饰器有
*args
)。你可以这样做:你还可以稍微简化你的装饰器。它实际上并不需要
__get__
机制。functools.wraps 是一个辅助装饰器,它使包装器模仿原始函数(即它复制函数名称、文档字符串和类似的东西)。它将使调试变得更容易,因为您将知道异常源自何处等。
I'm still not 100% sure I fully understand your problem. You say that "Since i cannot get the original method, i don't know how many parameters it has to map them", but you don't need access to the original method to call by variable number of arguments (since the decorator has
*args
). You can do something like this:You can also simplify your decorator a bit. It doesn't really need the
__get__
mechanism.The
functools.wraps
is a helper decorator that makes the wrapper mimic the original function (i.e. it copies the function name, docstring and stuff like that). It will make debugging easier, since you will know where exceptions are originating from etc.首先,对评论我的错误感到抱歉,现在你的最后一个代码将无法像你一样工作(你的方法不再被装饰),因为要理解装饰器,你必须看到这个 :
相当于:
在你最新的情况下
saveconfig
返回self.f
在我们的代码中等于getip
所以在这种情况下这个代码:相当于:
所以基本上它不做没有什么。
一种解决方法是将包装的函数保存在包装函数中,如下所示:
现在您可以:
希望这可以有所帮助:)
First of all sorry about the comment my mistake, now for your last code will not work as you which (your method is not decorated anymore) because to understand decorator you have to see this :
is equivalent to:
and in your latest case
saveconfig
returnself.f
which is in our code equal togetip
so in this case this code:is equivalent to :
so basically it don't do nothing.
A work around can be by saving the wrapped function in the wrapping one like this:
and now you can :
Hope this can help :)