为什么在这个方法中没有使用 `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
导入的函数使用,这也是一个可能的混淆来源。就您的目的而言,那是完全不同的事情。
我的印象是 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
导入的函数使用,这也是一个可能的混淆来源。就您的目的而言,那是完全不同的事情。