Why is `self` not used in this method?

不羁岁月 提交于 2020-01-03 02:57:09

问题


I was under the impression that methods within Python classes always require the self argument (I know that it doesn't actually have to be self, just some keyword). But, this class that I wrote doesn't require it:

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()

See? No self. When I include a self argument to make_archive, I get a TypeError: make_archive() missing one positional argument error. In my search to figure out why this is happening, I actually copied and tried to run a similar program from the docs:

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

and I get the same error!

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

In the same module that contains the Zipper() class, I have multiple classes that all make use of self. I don't understand the theory here, which makes it difficult to know when to do what, especially since a program copied directly from the docs (this is the docs page) failed when I ran it. I'm using Python 3.5 and 3.4 on Debian Linux. The only thing that I can think of is that it's a static method (and the Zipper.make_archive() as written above works fine if you include @staticmethod above the make_archive method), but I can't find a good explanation to be sure.


回答1:


You are trying to use it as a static method. In your example;

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

    def f(self):
       return 'hello world'

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

Calling MyClass.f() assumes f is static for MyClass. You can make it static as:

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

MyClass.f()



回答2:


The thing with self is that it's added implicitly. That is, the calling code says Myclass().f(), but the callee sees Myclass().f(self). It also implies that the method is called from some instance of Myclass, which is placed in self variable. The point is that methods are probably somehow using and/or modifying instance data (otherwise why would they be in that class?) and it's handy to have the instance in question automatically supplied.

If you don't need the instance data, you should use either @staticmethod if it's actually more like a function than object method or @classmethod if the method is meant to be inherited and possibly used differently by different classes. See @pankaj-daga answer for a little intro to staticmethods.

The Foo.bar() syntax is also used by functions imported via import Foo instead of from Foo import bar, which is also a possible source of confusion. That, for your purposes, is an entirely different thing.



来源:https://stackoverflow.com/questions/39803950/why-is-self-not-used-in-this-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!