define_method 在 Python

define_method in Python

我想为 Python class 动态定义一些方法。我用谷歌搜索了一会儿,发现 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 class 上的原始实现,如下所示(有一个错误,它总是将最后一个 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) 

发生的事情是你设置了例如'with_red' MyColor 实例上的属性到 Base 构造函数中定义的本地函数 - 请注意,这不是 class 方法,只是一个函数,它接受 2 个参数:'self' 和 'value':

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

ArgSpec(args=['self', 'value'], varargs=None, 关键字=None, 默认值=None)

一个简单的解决方法是让这个函数接受一个参数:

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

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

另一种选择是在 class 上设置 'with_red' 属性 - 这使它成为一种方法,然后隐式传递 self ,你可以保留 _with_field 带有两个参数的签名。