3

I am new to Python so please don't flame me if I ask something too noobish :)

1.

Consider I have a class:

class Test:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def wow():
        print 5 * 5

Now I try to create an object of the class:

x = Test(3, 4)

This works as expected. However, when I try to call the method wow(), it returns an error, which is fixed by changing wow() to:

def wow(self)

Why do I need to include self and if I don't, what does the method mean?

2. In the definition of __init__:

def __init__(self, x, y):
   self.x = x
   self.y = y

Why do I need to declare x and y, when I can do this:

def __init__(self):
    self.x = x
    self.y = y

I hope I am being clear...

Thanks for your time.

7
  • 4
    @Andy you should ask two separate questions. Commented Jun 16, 2010 at 13:36
  • @Andy: Which tutorial are you using? Please provide the name or a link. Commented Jun 16, 2010 at 14:10
  • 1
    @S.Lott: Python Tutorials on their website. Commented Jun 16, 2010 at 14:17
  • @S.Lott; You have 30 years of experience, I just started. I don't know what your intention is, but my question was genuine. Commented Jun 16, 2010 at 14:19
  • 1
    @Andy: I have no idea how much experience you have, or anything else. I'm asking a question to try and understand what you're talking about. I'm not you. I don't understand what you're doing or what you've learned or how you could have arrived at this question. And without help from you, I'll never know these things. You're using the python tutorials on their website? Where did you see code like the code you posted? Commented Jun 16, 2010 at 14:51

6 Answers 6

4

If you do that :

def __init__(self):
  self.x = x
  self.y = y

you assign the gobal vars x and y (it they exists ) to your instance

with :

def __init__(self, x, y):
      self.x = x
      self.y = y

you assign what you give as parameter to the constructor

and that is a lot more flexible :-)

Sign up to request clarification or add additional context in comments.

Comments

2

The instance reference in Python is explicit. That way it can be manipulated by e.g. decorators before finally being passed to the method.

We need to declare x and y as arguments to the function so that we can use their names within the function, bound to the arguments passed in the corresponding function call.

4 Comments

Suppose if I have an attribute that I don't want to be instantiated immediately, is it ok if I do this: def __init__(self, x): try: self.y = foo // do something here except: if the condition is not met, don't create it
Sure, but it will have to be a global. And don't use a bare except.
I don't see any such conflict in the code you pasted. And don't shadow file.
Of course. Python's dynamic nature means that symbol lookups aren't done until the code is actually executed.
1

Just to be clear

Why do I need to declare x and y, when I can do this:

def __init__(self):
    self.x = x
    self.y = y

This ^ will only work if x and y can be found at runtime - if they haven't been passed in then they must have been set elsewhere (globally) or it will generate an error.

>>> class c:
    def __init__(self):
        self.x = x

>>> x = 1
>>> q = c()
>>> q.x
1
>>> del x
>>> q.x
1
>>> w = c()

Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    w = c()
  File "<pyshell#14>", line 3, in __init__
    self.x = x
NameError: global name 'x' is not defined
>>> 
>>> w = c(2)

Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    w = c(2)
TypeError: __init__() takes exactly 1 argument (2 given)

This is why you want / need to specify them as parameters - it might work with the global lookup but it would probably violate the "principle of least astonishment"

Comments

1

self is a "magic" name - it can really be anything, but self is used for consistency and clarity. To answer your question, each class method/function requires an explicit reference to the class as the first parameter. Using Ipython:

In [66]: class Test:
   ....:     def __init__(self):
   ....:         pass
   ....:     def wow(self):
   ....:         print self
   ....:
   ....:

In [67]: x = Test()

In [68]: x.wow()
<__main__.Test instance at 0x0159FDF0>

Your second example won't actually work unless you already have an x and y in your namespace.

For instance, if you defined your class:

class Test:
    def __init__(self):
        self.x = x
        self.y = y

and tried

x = Test()

it will throw a NameError.

However if you write:

x = 3
y = 4
test = Test()

then it will work. However, it's not a good idea to do such a thing. For the reason why read line 2:

In [72]: import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

2 Comments

self is most definitely not a magic name: it is quite simply a name adopted by convention.
"self" is not magic because of the letters it is comprised of, but because of where it appears. </restate>
0
  1. In Python, methods should always take "one extra" argument, which is the reference to the instance the method is being called on. This is automatic in other languages such as Java, C#, etc. but Python is verbose about it.

  2. That doesn't make sense. Where are x and y in that example? If you want the constructor to take two arguments which populate the object, define it as such. Otherwise, you're doing something else.

Comments

0

Python is different from languages like C++ and Java in that the object instance reference is passed explicitly.

That is, if you have an object which is an instance of the class and you want to invoke a method that operates on that instance (e.g., reads its fields), you use the self references as the object.

In c++ and Java, you have an implicit "this" reference that is present in the compiled version of your program but not in the source code. You use the static keyword to make it into a class method that does not have a "this".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.