为什么在这个方法中没有使用 `self`?

Why is `self` not used in this method?

我的印象是 Python classes always 中的方法需要 self 参数(我知道它不需要实际上不必是 self,只是一些关键字)。但是,我写的 class 不需要它:

import ZipFile
import os
class Zipper:
    def make_archive(dir_to_zip):
        zf = zipfile.ZipFile(dir_to_zip + '.zip', 'w')
        for filename in files:
            zf.write(os.path.join(dirname, filename))
        zf.close()

看到了吗?没有self。当我在 make_archive 中包含一个 self 参数时,我得到一个 TypeError: make_archive() missing one positional argument 错误。为了弄清楚为什么会这样,我实际上从文档中复制并尝试 运行 一个类似的程序:

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

print(MyClass.f())  # I added this statement to have a call line

我得到了同样的错误!

TypeError: f() missing 1 required positional argument: 'self'

在包含 Zipper() class 的同一模块中,我有多个 class 都使用了 self。我不明白这里的理论,这让我很难知道什么时候该做什么,尤其是当我 运行 直接从文档 (this is the docs page) 复制的程序失败时。我在 Debian Linux 上使用 Python 3.5 和 3.4。我唯一能想到的是它是一个静态方法(如果你在 make_archive 方法之上包含 @staticmethod,上面写的 Zipper.make_archive() 工作正常),但我不能找一个好的解释来确定。

您正在尝试将其用作静态方法。在你的例子中;

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
       return 'hello world'

a = MyClass()
a.f()  # This should work.

调用 MyClass.f() 假定 f 对于 MyClass 是静态的。您可以将其设为静态:

class MyClass:
    @staticmethod
    def f():  # No self here
       return 'hello world'

MyClass.f()

self 的问题在于它是 隐式添加的 。也就是说,调用代码说 Myclass().f(),但被调用者看到 Myclass().f(self)。它还暗示该方法是从 Myclass 的某个实例调用的,该实例位于 self 变量中。关键是方法可能以某种方式使用 and/or 修改实例数据(否则为什么它们会在那个 class 中?)并且自动提供有问题的实例很方便。

如果您不需要实例数据,您应该使用 @staticmethod 如果它实际上更像一个函数而不是对象方法,或者 @classmethod 如果该方法是为了继承并且可能不同的 classes 使用不同。有关静态方法的一些介绍,请参阅@pankaj-daga 的回答。

Foo.bar() 语法也被通过 import Foo 而不是 from Foo import bar 导入的函数使用,这也是一个可能的混淆来源。就您的目的而言,那是完全不同的事情。