Python, __init__ and self confusion
Asked Answered
M

5

3

Alright, so I was taking a look at some source when I came across this:

>>> def __parse(self, filename):
...         "parse ID3v1.0 tags from MP3 file"
...         self.clear()
...         try:
...             fsock = open(filename, "rb", 0)
...             try:
...                 fsock.seek(-128, 2)
...                 tagdata = fsock.read(128)
...             finally:
...                 fsock.close()
...             if tagdata[:3] == 'TAG':
...                 for tag, (start, end, parseFunc) in self.tagDataMap.items():
...                     self[tag] = parseFunc(tagdata[start:end])
...         except IOError:
...             pass
... 

So, I decided to test it out.

 >>> __parse("blah.mp3")

And, I received this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __parse() takes exactly 2 arguments (1 given)

This wouldn't be the first time I've encountered this, I keep thinking I'm meant to include self in the argument parameter list, but I know that that's not right. Could someone explain to me why this happens a lot with code I try to play around with, I suppose its due to my level of understanding about the terms, I barely even understand what init or self does, or why it's relevant. def x(b): print b is the same as def x(self, b): self.b = b print self.b isn't it? Why does it matter so much!

I just want a basic explanation, so I can get this out of my mind,thanks.

Motorist answered 23/3, 2009 at 18:20 Comment(0)
F
8

The def __parse was inside some class definition.

You can't pull the method defs out of the class definitions. The method function definition is part of the class.

Look at these two examples:

def add( a, b ):
    return a + b

And

class Adder( object ):
    def __init__( self ):
        self.grand_total = 0
    def add( self, a, b ):
        self.grand_total += a+b
        return a+b

Notes.

  1. The function does not use self.

  2. The class method does use self. Generally, all instance methods will use self, unless they have specific decorators like @classmethod that say otherwise.

  3. The function doesn't depend on anything else else.

  4. The class method depends on being called by an instance of the class Adder; further, it depends on that instance of the class Adder having been initialized correctly. In this case, the initialization function (__init__) has assured that each instance of Adder always has an instance variable named grand_total and that instance variable has an initial value of 0.

  5. You can't pull the add method function out of the Adder class and use it separately. It is not a stand-alone function. It was defined inside the class and has certain expectations because of that location inside the class.

Fencesitter answered 23/3, 2009 at 18:23 Comment(11)
Ah, so init/self should be used with classes and not with def's that aren'tinside classes?Motorist
Or rather, def init should be used in classes, and def whatever(self, ...) should be used in classes also, modules/methods on their own shouldn't have self's?Motorist
Technically, "self" is not a keyword. In practice, you should pretend that it is.Bennir
Brian, ok. I'm just confused as to how to implemenet this. when i have a method on it's out without a class, should i have a self along with it? I can understand not having an init, but a self, is it necessary to have?Motorist
functions on their own, I mean. like a function that says hello n, def hi(self, n): self.n = n; print "hello %s" % self.n ? where's the usefulness in that?Motorist
eh, that doesnt even work. I guess I'll just reserve self/init for methods used in classes.Motorist
Perhaps your confusion is an indication that the given answer is not what you're looking for.Brisk
@S.Lott: Your code-formatting style breaks PEP8 rules without any reason. Why do you use spaces after '(' and before ')'? Code examples on public sites should obey the PEP8 guide if there is no particular reason to use other styles.Adscription
@J.F. Sebastian: Sorry, I break PEP8 rules for a reason. I don't see a need to repeat that reason with every single code sample.Fencesitter
@S.Lott: A link to description of the reason behind your unusual code-formatting style would suffice.Adscription
@J.F. Sebastian: Sadly, comments can't be edited to remove the "for no reason" and "no particular reason", which aren't true. The "not PEP-8", however is totally true.Fencesitter
B
2

Functions/methods can be written outside of a class and then used for a technique in Python called monkeypatching:

class C(object):
  def __init__(self):
    self.foo = 'bar'

def __output(self):
  print self.foo

C.output = __output
c = C()
c.output()
Brisk answered 23/3, 2009 at 18:32 Comment(2)
Seems kind of a round-about method. Do you have a non-trivial example?Betsey
I can give lots of examples but they all reduce to setting an attribute on a class to a function defined outside of it. Monkeypatching is most useful when you can't modify the class itself, either because it's part of another library or because you don't have the source code.Brisk
L
1

Looks like you're a bit confused about classes and object-oriented programming. The 'self' thing is one of the gotchas in python for people coming from other programming languages. IMO the official tutorial doesn't handle it too well. This tutorial seems quite good.

If you've ever learnt java, self in python is very similar to this in java. The difference is that python requires you to list self as the first argument to every function in a class definition.

If python is your first programming language (or your first object-oriented language), you could remember this as a simple rule-of-thumb: if you're defining a function that's part of a class, you need to include self as the first argument. If you're defining a function that's not part of a class, you shouldn't include self in the arguments. You can't take a class function and make it stand-alone without doing some (or possibly a lot of) extra coding. Finally, never include self as an argument when calling a function.

There are exceptions to those rules, but they're not worth worrying about now.

Lorenalorene answered 23/3, 2009 at 22:5 Comment(0)
I
0

self is passed in automatically by the instancemethod wrapper on classes. This function isn't wrapped; it's not a method, it's just a function. It doesn't even make sense without being attached to a class, since it needs the self parameter.

Implore answered 23/3, 2009 at 18:23 Comment(0)
B
0

As an aside, it is possible to create static methods of a class in Python. The simplest way to do this is via decorators (e.g. @staticmethod). I suspect this kind of thing is usually not the Pythonic solution though.

Bennir answered 23/3, 2009 at 18:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.