【问题标题】:instance methods and static methods in python classespython类中的实例方法和静态方法
【发布时间】:2018-03-07 13:18:40
【问题描述】:

所以在 python 的 docutils 包中有一个类 (Image) 有一个方法 (align)。据我了解,除非将它们装饰为@classmethod 或@staticmethod,否则方法将self 作为第一个参数,但是align 不会。相关代码复制如下(full code here)。

class Image(Directive):

    def align(argument):
        # This is not callable as self.align.  We cannot make it a
        # staticmethod because we're saving an unbound method in
        # option_spec below.
        return directives.choice(argument, Image.align_values)

我将此代码用作我自己的目的的基础,并且我尝试过给 align 一个 self 参数并将其转换为静态方法(在更改名称以免与 self.align 冲突之后),但无论哪种方法都有错误。怎么回事?

【问题讨论】:

  • 您能提供您遇到的错误吗?
  • with @staticmethod: 'staticmethod' 对象不可调用。添加了“self”:align_option() 缺少 1 个必需的位置参数:“arg”。
  • 实际上这是记录在案的:“这不能作为 self.align 调用。我们不能将其设为静态方法,因为我们在下面的 option_spec 中保存了一个未绑定的方法。”
  • 文档不是很清楚,但是。我读到了,我的第一个想法是“如果它不是方法,你为什么要定义函数?”我花了一段时间才意识到该函数(至少,通过类属性访问)不打算在类外使用。

标签: python class static-methods


【解决方案1】:

不需要将第一个参数命名为self;这只是一个惯例。在以下代码中

i = Image()
i.align()

align 方法将被调用,参数argument 引用对象i

以下函数的行为相同:

def align(self):
    return directives.choice(self, Image.align_values)

(只需将argument 替换为更常见的self)。


在上下文中,函数align 从未打算成为一种方法;作者似乎只是定义了一个存储在options_spec 字典中的函数。通过在函数引用保存后删除名称,可以在不污染类的命名空间的情况下达到预期的效果:

option_spec = {'alt': directives.unchanged,
               'height': directives.length_or_unitless,
               'width': directives.length_or_percentage_or_unitless,
               'scale': directives.percentage,
               'align': align,
               'name': directives.unchanged,
               'target': directives.unchanged_required,
               'class': directives.class_option}
del align

或者放弃def 语句——这是一个非常简单的函数——并使用lambda 表达式来创建函数。

option_spec = {'alt': directives.unchanged,
               'height': directives.length_or_unitless,
               'width': directives.length_or_percentage_or_unitless,
               'scale': directives.percentage,
               'align': lambda x: directives.choice(x, Image.align_values)
               'name': directives.unchanged,
               'target': directives.unchanged_required,
               'class': directives.class_option}

【讨论】:

  • 这就是我的想法,但是,至少在我理解代码的情况下,传递给 align 的是一个真正的参数(特别是,无论用户为 align 选项输入什么),而不仅仅是 self with一个不同的名字。 directives.choice 函数检查参数 1 是否是元组参数 2 的成员。由于 Image.align_values 是字符串元组,这意味着参数 1 必须是字符串而不是类 Image 的实例。跨度>
  • 啊,从技术上讲,它是一个实例方法,但是它永远不会被这样使用。相反,该函数存储在 dict (option_spec) 中,其中 is 仅用作常规函数。类似i.option_spec['align'](foo)
  • dict 中保存引用后添加del align 可能是一个好主意,以便从class 语句的主体中删除名称,防止它被存储为类的属性。那么就不会有名为align的伪方法。
  • 换句话说,如果打算通过类访问,作者应该将其标记为静态方法。
  • 感谢您添加编辑。我仍然有点困惑,但我有点明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-13
  • 2021-08-03
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多