在类方法和子类方法上使用Python装饰器
目标:让类的方法可以被装饰。当一个类的方法被装饰后,它会被存储在一个字典里,这样其他类的方法就可以通过字符串名称来引用它。
动机:我想实现类似于ASP.Net中的WebMethods功能。我是在谷歌应用引擎上构建这个,但这并不影响我遇到的困难。
如果能正常工作,它的样子会是这样的:
class UsefulClass(WebmethodBaseClass):
def someMethod(self, blah):
print(blah)
@webmethod
def webby(self, blah):
print(blah)
# the implementation of this class could be completely different, it does not matter
# the only important thing is having access to the web methods defined in sub classes
class WebmethodBaseClass():
def post(self, methodName):
webmethods[methodName]("kapow")
...
a = UsefulClass()
a.post("someMethod") # should error
a.post("webby") # prints "kapow"
可能还有其他方法可以实现这个功能。我非常欢迎任何建议。
3 个回答
0
class UsefulClass(WebmethodBaseClass):
def someMethod(self, blah):
print(blah)
@webmethod
def webby(self, blah):
print(blah)
class WebmethodBaseClass():
def post(self, methodName):
method = getattr(self, methodName)
if method.webmethod:
method("kapow")
...
def webmethod(f):
f.webmethod = True
return f
a = UsefulClass()
a.post("someMethod") # should error
a.post("webby") # prints "kapow"
当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。
1
这看起来是满足你需求的最简单方法:
webmethods = {}
def webmethod(f):
webmethods[f.__name__] = f
return f
还有,在 WebmethodBaseClass
中,
def post(self, methodName):
webmethods[methodName](self, "kapow")
我觉得你可能想要的东西不太一样(比如,不同的子类用不同的命名空间,而不是一个全局的 webmethods
字典……?),但没有更多的信息,我很难猜出你的需求和你所描述的具体要求有什么不同。所以,也许你可以告诉我们这个简单的方法在哪些方面没有达到你的期望,这样我们就可以根据你真正想要的来进行改进。
4
这其实没必要。直接用 getattr
就可以了:
class WebmethodBaseClass():
def post(self, methodName):
getattr(self, methodName)("kapow")
唯一需要注意的是,你得确保只有那些打算作为网络方法使用的函数才能这样用。最简单的办法,我觉得,是约定非网络方法的名字前面加个下划线,然后让 post
方法拒绝处理这些名字。
如果你真的想用装饰器,可以试试这个:
def webmethod(f):
f.is_webmethod = True
return f
然后让 post
在调用方法之前检查一下 is_webmethod
这个属性是否存在。