Python中的define_method

时间:2018-06-04 07:49:58

标签: python metaprogramming setattr

我想为Python类动态定义一些方法。我用谷歌搜索了一段时间,发现this。我稍微更改了代码以满足我的要求。

这是我的代码:

class Base(object):

  def add_method(self, field):
    def func(self, value):
      self.colors[field] = value
      return self
    return func

  def define_method(self, *fields):
    for field in fields:
      setattr(self, "with_" + field, self.add_method(field))


class MyColor(Base):

  def __init__(self):
    self.colors = {
      "black": "000",
      "red": "f00",
      "green": "0f0"
    }

    # ========== ==========
    # by doing this, I assume `with_red()` and `with_green()`
    # will be generated, and they're chain-able.
    super(MyColor, self).define_method("red", "green")


s = MyColor()
s.with_red("111").with_green("222")
print(s.colors) 
# should output: {"black": "000", "red": "111", "green": 222}

代码会引发错误:

Traceback (most recent call last):
  File "main.py", line 26, in <module>
    s.with_red("111").with_green("222")
TypeError: _with_field() missing 1 required positional argument: 'value'

有什么问题?

谢谢你的时间!

==========编辑==========

抱歉,我更改了Base课程的原始实现,如下所示(有一个错误,它总是会更改传递给field的最后define_method())。 @ Alex的回答。

class Base:

  def define_method(self, *fields):
    for field in fields:
      def _with_field(self, value):
        self.colors[field] = value
        return self
      setattr(self, "with_" + field, _with_field) 

1 个答案:

答案 0 :(得分:2)

你要设置的是&#39;的 with_red &#39;将MyColor实例上的属性赋予Base构造函数中定义的局部函数 - 请注意,这不是一个类方法,只是一个函数,它需要两个参数:&#39; self &#39;和&#39; &#39;:

import inspect
...
s = MyColor()
print(inspect.getargspec(s.with_red))

ArgSpec(args = [&#39; self&#39;,&#39; value&#39;],varargs = None,keywords = None,defaults = None) < /强>

这里的一个简单修复就是让这个函数只需要一个参数:

def _with_field(value):
   self.colors[field] = value
   return self

通过此更改,您的代码将生成预期的输出。

另一种选择是设置&#39; with_red &#39;类的属性 - 这使它成为一个方法,然后隐式传递self,你可以用两个参数保持_with_field签名。