【问题标题】:Python passing in a list of parameters to be used as dynamic propertiesPython 传入要用作动态属性的参数列表
【发布时间】:2013-03-25 15:57:43
【问题描述】:

我有这个是 Flask 中 Jinja2 模板特有的(但与任何一个都没有具体关系,只是我正在构建更通用的东西的上下文):

class MultipleMacroFor(object):
    def __init__(self, macro):
        self.macro = macro

    def renderable(self, macro_var):
        return get_template_attribute(self.macro, macro_var)

class ResponseItemMacros(MultipleMacroFor):
    def __init__(self):
        super(ResponseItemMacros, self).__init__(macro="macros/response_items.html")

    @property
    def general_macro(self):
        return self.renderable('general_macro')

RI = ResponseItemMacros()

一个用例的例子:

 RI.general_macro # returns the renderable 'general_macro' from 'macros/response_items.html' that can be used with in a Jinja2 template

我想变成这样:

class MultipleMacroFor(object):
    def __init__(self, macro, which_macros):
          self.macro = macro
          self.which_macros = which_macros

     # take which_macros and have them each be returnable as in the function above but
     # respond to the more general case, not specifically requiring construction  
     # @property
     # def (passed in var which_macro)(self):
     #   return self.renderable(passed in var which_macro)

RI = MultipleMacroFor(macro="macros/response_items.html", macros=['general', 'etc', 'etal'])

然后用例:

RI.general_macro #as above but without having to construct the intermediate ResponseItemsMacros class

并将传入的列表作为属性调用,仅根据传入的列表动态构造,而不是像第一个示例那样手动构造。第一个示例需要从两个类手动构建我要使用的实例。第二个是希望只使用 1 个可以用要调用的属性实例化的类,这将通过可渲染函数工作以生成相关的命名宏。

只有我不确切知道如何做到这一点。任何输入表示赞赏。

【问题讨论】:

  • 我不明白你的问题,也不明白例子和问题之间的关系。你能更清楚地解释你想要什么,也许给出一些使用MultipleMacroFor的代码?
  • 很公平,已添加说明

标签: python list parameter-passing args


【解决方案1】:

你不能拥有每个实例的属性(或者至少不能不弄乱 get_attribute,这是你真正应该避免的事情)。最简单的解决方案是使用 getattr

class MultipleMacroFor(object):
    def __init__(self, macro, names):
        self._macro = macro
        self._names = names

    def get_renderable(self, macro_var):
        return get_template_attribute(self.macro, macro_var)

    def __getattr__(self, name):
        if name in self._names:
            return self.get_renderable(name)
        raise AttributeError(
            "object %s has no attribute '%s'" % (
                type(self).__name__, name)
            )

一个更复杂的方法是动态构建一个子类然后实例化它。

class MultipleMacroFor(object):
    def __init__(self, macro, names):
        self._macro = macro
        self._names = names


    def get_renderable(self, macro_var):
        return get_template_attribute(self.macro, macro_var)

def MultipleMacroForFactory(macro, names):
    attrs = dict()
    for name in names:
        attrs[name] = property(
            lambda self, name=name: self.get_renderable(name)
            )

    clsname = "MultipleMacroFor%s" % "".join(
        name.capitalize() for name in names
        )

    return type(clsname, (MultipleMacroFor,), attrs)(macro, names)

【讨论】:

  • 第二个似乎比我在寻找 atm 更复杂,但第一个是我正在寻找的,但在最初被问到时不太明白如何去做,所以让我试试
  • 我不明白你为什么提到__getattr__ 并用__getitem__ 写一个类。
  • @blueblank:第二种解决方案的好处是属性通过自省可见。作为一个额外的奖励,描述符首先出现在名称查找规则中,而 __getattr__ 是在尝试了所有其他可能的解决方案之后的最后手段,但这确实是微优化
猜你喜欢
  • 2018-04-17
  • 2020-09-04
  • 2011-04-18
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多