我正在尝试为Pub / Sub类型的应用程序创建一个通用的Python类,其中模型定义为每种我们拥有的资源X类型指定了三种方法:
new_X
changed_X
deleted_X
我已经将代码抽象为一个方法,该方法接受有关类型和操作的参数:
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()))
但这然后需要我手写每个定义的方法,尽管每一行都是一行:
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)
我试图找到一个更好的模式,以进一步抽象它,这样我就不必手工编写这些单行方法。因为方法名称映射到我的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()
理想情况下,此通用方法将捕获如下调用:
publisher.new_resources([])
publisher.new_items([])
publisher.new_banks([])
无需我手动编写每个方法的代码...是否有一种优雅的方法可以做到这一点?我当时想也许可以用__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
python大神给出的解决方案
我不太确定您的代码实际上在做什么,但是从简单的角度来看,我想捕获通用调用,例如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)
运行此命令时生成的输出是:
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 )
代码注释
您非常接近,但是遇到了一些与您的define_verb_and_type()
以及与此相关的问题。我对本节进行了一些简化,并增加了调试打印语句的负载。目前,我只在线编码,所以我没有一个好的调试器,因此我使用print进行调试。
我所做的一个更改是,我没有对item in [ ... list ...]
进行测试,而是将其拆分,然后对实际的verb
和obj_type
进行了测试。您甚至可能希望放弃obj_type
的测试。保留对注释框中的列表进行的工作版本测试。
我与您的代码有关的一个问题是使用_pub_wrapper
的id_list
。我不太清楚您要在此处实现的目标,并且有点希望将其作为实例变量或以其他方式查看此列表的添加/删除。
我还添加了一个新示例来显示命名和未命名的参数。前者出现在kwargs
参数中,而后者出现在args
参数中。
换句话说,我不太了解我是否正确理解了您的问题,以及您希望我们审查什么代码。但是,我在此处的答案中提供的代码确实提供了所需的通用调用方法,并有望帮助您进行编码项目。
用大写字母拆分字符串,但忽略AAA Python Regex - python我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…
Python:同时在for循环中添加到列表列表 - python我想用for循环外的0索引值创建一个新列表,然后使用for循环添加到相同的列表。我的玩具示例是:import random data = ['t1', 't2', 't3'] masterlist = [['col1', 'animal1', 'an…
在Flask中测试文件上传 - python我在Flask集成测试中使用Flask-Testing。我有一个表单,该表单具有我要为其编写测试的徽标的文件上传,但是我不断收到错误消息:TypeError: 'str' does not support the buffer interface。我正在使用Python3。我找到的最接近的答案是this,但是它对我不起作用。这是我的许多尝…
在熊猫中,如何从单词列表或单词集中选择数据框中的短语? - python在Python3和熊猫中,我具有数据框:df_projetos_api_final.info() <class 'pandas.core.frame.DataFrame'> Int64Index: 93631 entries, 1 to 93667 Data columns (total 21 columns): AnoMat…
在Python中迭代OrderedDict - python我有以下OrderedDict:OrderedDict([('r', 1), ('s', 1), ('a', 1), ('n', 1), ('y', 1)]) 实际上,这表示单词中字母的出现频率。第一步-我将使用最后两个元素来创建一个这样的联合元组; pair…