有啥理由给 self 一个默认值吗?

Posted

技术标签:

【中文标题】有啥理由给 self 一个默认值吗?【英文标题】:Is there any reason for giving self a default value?有什么理由给 self 一个默认值吗? 【发布时间】:2017-01-11 01:45:20 【问题描述】:

我正在浏览一些代码,我注意到一行引起了我的注意。代码类似于下面的例子

class MyClass:
    def __init__(self):
        pass

    def call_me(self=''):
        print(self)

这看起来像我见过的任何其他类,但是 str 正在作为 self 的默认值传入。

如果我打印出self,它的行为正常

>>> MyClass().call_me()
<__main__.MyClass object at 0x000002A12E7CA908>

这一直困扰着我,我无法弄清楚为什么要使用它。是否有任何理由将str 实例作为self? 的默认值传入

【问题讨论】:

听起来有人也想让MyClass.call_me() 工作。然而,这不是一个特别好的主意,他们本可以改为 classmethod 如果call_me是从类本身而不是从实例调用的,那么''作为实例传递,方法调用不会引发错误。 【参考方案1】:

简短的回答是肯定的。这样,您可以将函数调用为:

MyClass.call_me()

不实例化MyClass,将打印一个空字符串。

要给出更长的答案,我们需要看看幕后发生了什么。

当你创建类的实例时,会调用__new____init__来创建它,即:

a = MyClass()

大致相当于:

a = MyClass.__new__(MyClass)
MyClass.__init__(a)

每当您在创建的实例a上使用某种方法时:

a.call_me()

它被“替换”为MyClass.call_me(a)

因此,为call_me 设置一个默认参数允许您不仅将这个函数作为实例的方法调用,在这种情况下,self 本身就是一个实例,而且还作为一个静态类方法。

这样,就不会调用MyClass.call_me(a),而是调用MyClass.call_me()。因为参数列表是空的,所以默认参数被分配给self,并打印出想要的结果(空字符串)。

【讨论】:

【参考方案2】:

不是真的,这只是一种奇怪的方式,它在通过类调用时不会引发错误:

MyClass.call_me()

工作正常,因为即使没有像实例一样隐式传递,也提供了该参数的默认值。如果没有提供默认值,那么在调用时,这当然会为我们都喜欢的 args 提高 TypeError。至于他为什么选择一个空字符串作为值,只有他自己知道

归根结底,这比实际情况更令人困惑。如果您需要做类似的事情,我建议使用带有默认参数的简单staticmethod 来实现类似的效果。

这样你不会难倒任何人阅读你的代码(就像写这个的开发者和你一样;-):

@staticmethod
def call_me(a=''):
    print(a)

如果您需要访问类属性,您总是可以选择classmethod 装饰器。这两个(classstatic 装饰器)还有一个次要目的,就是让阅读您的代码的其他人清楚地了解您的意图。

【讨论】:

以上是关于有啥理由给 self 一个默认值吗?的主要内容,如果未能解决你的问题,请参考以下文章

能设置laydate里的time时间默认值吗

Java 类有默认值吗?

函数调用的结果可以用作默认参数值吗?

Wildfly 中的 @Dependent 范围不是默认值吗?

angularjs路由可以有默认参数值吗?

主函数可以有默认参数值吗?