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.
-
4@Andy you should ask two separate questions.systempuntoout– systempuntoout2010年06月16日 13:36:02 +00:00Commented Jun 16, 2010 at 13:36
-
@Andy: Which tutorial are you using? Please provide the name or a link.S.Lott– S.Lott2010年06月16日 14:10:25 +00:00Commented Jun 16, 2010 at 14:10
-
1@S.Lott: Python Tutorials on their website.Andy– Andy2010年06月16日 14:17:37 +00:00Commented 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.Andy– Andy2010年06月16日 14:19:09 +00:00Commented 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?S.Lott– S.Lott2010年06月16日 14:51:21 +00:00Commented Jun 16, 2010 at 14:51
6 Answers 6
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 :-)
Comments
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
file.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
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.</restate>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.
That doesn't make sense. Where are
xandyin 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
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".