我正在尝试为Pub/Sub类型的应用程序创建一个通用的Python类,其中模型定义为我们拥有的每种类型的资源X指定了三种方法:
new_X
changed_X
deleted_X
Run Code Online (Sandbox Code Playgroud)
我已经将代码抽象为单个方法,它接受有关类型和操作的参数:
def _pub_wrapper(self, verb, obj_type, id_list):
ids = [str(i) for i in id_list]
self._pub(ids, '{0}.{1}'.format(verb,
obj_type.lower()))
Run Code Online (Sandbox Code Playgroud)
但这需要我手工编写每个定义的方法,尽管在一行中,每个方法:
def new_resources(self, id_list):
self._pub_wrapper('new', 'resources', id_list)
def changed_resources(self, id_list):
self._pub_wrapper('changed', 'resources', id_list)
Run Code Online (Sandbox Code Playgroud)
我试图找到一个更好的模式,进一步抽象,这样我就不必手写这些单行方法了.因为方法名称映射到我的pub/sub系统中的动词/类型,所以我想的是(伪代码可以遵循):
def __getattr__(self, item):
if name in [whitelist of approved methods]:
return ??? Some sort of partially defined version of self._pub_wrapper, with verb and obj_type filled in from parsing item ???
raise AttributeError()
Run Code Online (Sandbox Code Playgroud)
这种通用方法理想情况下会捕获如下调用:
publisher.new_resources([])
publisher.new_items([])
publisher.new_banks([])
Run Code Online (Sandbox Code Playgroud)
没有我必须手动编码这些方法...有一个优雅的方法来做到这一点?我想也许我可以用装饰器来做__getattr__,但不太确定如何返回一个装饰方法.尝试以下,但self._pub_wrapper()从未调用过该方法.
def define_verb_and_type(*args, **kwargs):
def wrap(func):
def wrapped_func(*args):
return func(*args, verb=kwargs['verb'], obj_type=kwargs['obj_type'])
return wrapped_func
return wrap
def __getattr__(self, item):
if item in ['new_resources', 'changed_resources', 'deleted_resources']:
verb = item.split('_')[0]
obj_type = item.split('_')[-1]
return define_verb_and_type(self._pub_wrapper, verb, obj_type)
raise AttributeError
Run Code Online (Sandbox Code Playgroud)
我不太确定您的代码实际上在做什么,但从简单的角度来看,我知道您想要捕获通用调用,例如publisher.new_resources( [] ),它应该自动生成对_pub_wrapper(new, resources, [])或 下面的调用_pub(...)。
这是一个工作示例:
class Test:
def _pub_wrapper(self, verb, obj_type, id_list):
print " Called _pub_wrapper(" , verb, ", ", obj_type, ", ", id_list, ")"
ids = [str(i) for i in id_list]
self._pub(ids, '{0}.{1}'.format(verb,
obj_type.lower()))
def _pub(self, ids, something):
print " Called _pub( ", self, ", ", ids, ", ", something, ")"
def __getattr__(self, item):
verb = item.split('_')[0]
obj_type = item.split('_')[-1]
if verb in ['new', 'changed', 'deleted'] and \
obj_type in ['resources', 'items', 'banks']:
def wrapper(*args, **kwargs):
print "Within wrapper: verb=", verb, ", obj_type=", obj_type, ", args=", args, ", kwargs=", kwargs
print "Within wrapper: ", verb, ", ", obj_type, ", ", args
return self._pub_wrapper(verb, obj_type, args[0])
return wrapper
raise AttributeError
"""
def __getattr__(self, item):
if item in ['new_resources', 'changed_resources', 'deleted_resources', 'changed_banks']:
verb = item.split('_')[0]
obj_type = item.split('_')[-1]
print verb, " vs ", obj_type
def wrapper(*args):
print "Within wrapper: ", verb, ", ", obj_type, ", ", args[0]
return self._pub_wrapper(verb, obj_type, args[0])
return wrapper
raise AttributeError
"""
def fake_new_resources(self, id_list):
self._pub_wrapper('new', 'resources', id_list)
t = Test()
print "Faking it... "
t.fake_new_resources([])
print "New tries"
t.new_resources([])
t.changed_banks([])
t.deleted_items(["hi", "bye"], 4, your=23, mine=42)
Run Code Online (Sandbox Code Playgroud)
运行时生成的输出是:
Faking it...
Called _pub_wrapper( new , resources , [] )
Called _pub( <__main__.Test instance at 0x1c366c> , [] , new.resources )
New tries
Within wrapper: verb= new , obj_type= resources , args= ([],) , kwargs= {}
Called _pub_wrapper( new , resources , [] )
Called _pub( <__main__.Test instance at 0x1c366c> , [] , new.resources )
Within wrapper: verb= changed , obj_type= banks , args= ([],) , kwargs= {}
Called _pub_wrapper( changed , banks , [] )
Called _pub( <__main__.Test instance at 0x1c366c> , [] , changed.banks )
Within wrapper: verb= deleted , obj_type= items , args= (['hi', 'bye'], 4) , kwargs= {'your': 23, 'mine': 42}
Called _pub_wrapper( deleted , items , ['hi', 'bye'] )
Called _pub( <__main__.Test instance at 0x1c366c> , ['hi', 'bye'] , deleted.items )
Run Code Online (Sandbox Code Playgroud)
您已经非常接近了,但是遇到了一些与您的define_verb_and_type()以及此调用相关的问题。我稍微简化了这一部分,并添加了调试打印语句的负载。目前我只在线编码,所以我没有好的调试器,因此我使用 print 进行调试。
我所做的一个更改是,item in [ ... list ...]我没有测试 ,而是之前拆分了该项目,并测试了实际的verb和obj_type。您甚至可能想放弃对obj_type. 在评论块中保留针对列表的工作版本测试。
我与您的代码相关的一个问题是_pub_wrapper您在哪里使用id_list. 我不太明白你想在这里实现什么,并且有点期望它以某种方式成为实例变量,或者看到此列表的添加/删除。
我还添加了一个新示例来显示命名和未命名参数。前者存在于kwargs参数中,后者存在于args参数中。
换句话说,我不太清楚我是否正确理解了您的问题,以及您希望我们审查哪些代码。但是我在这里的答案中提供的代码确实提供了您想要的通用调用方法,并希望能够帮助您在编码项目中取得进展。
| 归档时间: |
|
| 查看次数: |
184 次 |
| 最近记录: |