【问题标题】:Why doesn't string.Formatter.format have a "self" parameter?为什么 string.Formatter.format 没有“self”参数?
【发布时间】:2019-05-24 22:20:22
【问题描述】:

在阅读python的string模块的源码时,被Formatter这个类弄糊涂了。

Formatter 类中的format 方法(不是静态方法也不是类方法)没有self 作为输入参数def format(*args, **kwargs):,但以某种方式直接在方法中使用它。 self, *args = args.

请解释一下这个用法。

class Formatter:
    def format(*args, **kwargs):
        if not args:
            raise TypeError("descriptor 'format' of 'Formatter' object "
                            "needs an argument")
        self, *args = args  # allow the "self" keyword be passed
        try:
            format_string, *args = args # allow the "format_string" keyword be passed
        except ValueError:
            if 'format_string' in kwargs:
                ...
            else:
                ...
        return self.vformat(format_string, args, kwargs)

【问题讨论】:

标签: python string class self


【解决方案1】:

self 被假定为*args 中的第一个arg,并在此行中解压缩:

self, *args = args

在签名中声明一个没有 self 的实例方法在 Python 中是不常见的。

通过查看方法签名行的git history,我们可以看到最初存在self

如果格式字符串包含名为self 的变量,例如'I am my{self}',它的存在会导致错误,因此已将其删除。引入了从args 解包self 的异常模式来修复该错误。

错误报告和讨论是here

这是错误报告中的一个错误示例:

>>> string.Formatter().format('the self is {self}', self='bozo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: format() got multiple values for argument 'self'

【讨论】:

  • 答案是什么……但是为什么呢? self 引用始终是传递给类方法的第一个参数,那么当您可以为它创建一个参数时,为什么还要麻烦在方法内部使用元组解包来将 self 从位置参数中分离出来呢?跨度>
  • @snakecharmerb,谢谢。研究 git 历史的好技术。
【解决方案2】:

我假设您熟悉参数中的*args 语法。这只是未命名参数的任意列表。然后你有

self, *args = args  # allow the "self" keyword be passed

该评论非常明确。您将args(它是一个列表)拆分为第一个元素(我们通常称之为self,但它只是一个常规参数,始终是对象方法中的第一个),然后是其余的。因此,我们读取了self,一切都很好 - 不是立即,而是在函数中。

我在这里看到的唯一用例来自

if not args:
        raise TypeError("descriptor 'format' of 'Formatter' object "
                        "needs an argument")

这意味着我们期望做类似的事情

Formatter.format(formatterObj,format_string,...)

很多(不知道为什么,像工厂之类的东西?),所以如果我们忘记在我的示例中发送self - formatterObj,我们会收到一个详细错误。可能支持Formatter 类似没有format 方法但有vformat 方法的对象。不过似乎不太可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-20
    • 2015-08-21
    • 2016-06-22
    • 2022-06-15
    • 1970-01-01
    • 2015-09-30
    • 2019-02-13
    相关资源
    最近更新 更多