简体   繁体   中英

Why is `self` not used in this method?

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM