Why is `self` not used in this method?
Asked Answered
S

2

2

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.

Supermundane answered 1/10, 2016 at 7:10 Comment(3)
"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." The part that failed is not the part that you copied from the docs. The very next code snippet in that section illustrates "instantiation" of the class. The next couple of sections cover attributes (including methods) of the instance, etc. You need to read and understand the text in between the code snippets, not just test out the code.Trickle
Additionally, your terminology is all over the place. If you're trying to teach yourself the language just from the documentation, be warned that it may be a bumpy ride. In any event, be more careful with this; programming demands precision. StackOverflow is not really a place intended to help people learn the basics of a language, and especially not "how to program"; it's for solving specific technical problems that come up in your work.Trickle
I appreciate that StackOverflow is for "specific technical problems that come up in your work". I personally would consider this a specific technical problem that came up in my work, considering I asked the specific question "Why does this not require the argument self?" and I was working on a personal project when I came across the issue. I put in substantial research before asking this question, which is what's required. I have no idea what you mean about my terminology, but thanks for the warning. If you have a better place to ask programming questions at 2:30 AM, I'd love to here it.Supermundane
L
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()
Lochia answered 1/10, 2016 at 7:14 Comment(0)
J
1

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.

Jiggerypokery answered 1/10, 2016 at 9:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.