python – 编写一个通用的getattr()并根据attr名称填充方法参数

前端之家收集整理的这篇文章主要介绍了python – 编写一个通用的getattr()并根据attr名称填充方法参数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我正在尝试为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',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,obj_type)
    raise AttributeError
最佳答案
我不太清楚你的代码实际上在做什么,但从简单的角度来看,我得到你想要捕获泛型调用,比如publisher.new_resources([]),它会自动生成对_pub_wrapper的调用(new,resources,[])或_pub(…)下面的一个.

这是一个工作示例:

class Test:    
    def _pub_wrapper(self,id_list):
        print "  Called _pub_wrapper(",",id_list,")"
        ids = [str(i) for i in id_list]
        self._pub(ids,obj_type.lower()))

    def _pub(self,ids,something):
        print "    Called _pub( ",self,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=",obj_type=",args=",args,kwargs=",kwargs
                print "Within wrapper: ",args
                return self._pub_wrapper(verb,args[0])
            return wrapper
        raise AttributeError

    """        
    def __getattr__(self,item):
        if item in ['new_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: ",args[0]
                return self._pub_wrapper(verb,args[0])
            return wrapper
        raise AttributeError
    """

    def fake_new_resources(self,id_list):
        self._pub_wrapper('new',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,[] )
    Called _pub(  <__main__.Test instance at 0x1c366c>,[],new.resources )
New tries
Within wrapper: verb= new,obj_type= resources,args= ([],),kwargs= {}
  Called _pub_wrapper( new,new.resources )
Within wrapper: verb= changed,obj_type= banks,kwargs= {}
  Called _pub_wrapper( changed,banks,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>,deleted.items )

代码评论

你非常接近,但有一些与你的define_verb_and_type()相关的问题,以及调用它.我稍微简化了这一部分,并添加了大量的调试打印语句.目前我只在线编码,所以我没有一个好的调试器,因此我使用print进行调试.

我做的一个改变是,不是测试[… list …]中的项目,而是在之前拆分项目,并测试实际的动词和obj_type.你甚至可能想要放弃obj_type的测试.保持对注释块中的列表进行工作版本测试.

我与你的代码有关的一个问题是在你使用id_list的_pub_wrapper中.我不太明白你想要在这里实现什么,并且有点期望这可能是一个实例变量,或者看到添加/删除到这个列表.

我还添加了一个新示例来显示命名和未命名的参数.前者存在于kwargs参数中,而后者存在于args参数中.

换句话说,如果我正确理解你的问题,以及你希望我们审查哪些代码,我就不太了解.但是我的答案中提供的代码确实提供了您想要的通用调用方法,并希望能帮助您在编码项目中取得进展.

原文链接:https://www.f2er.com/python/438379.html

猜你在找的Python相关文章