Python calling class methods with the wrong number of parameters
I'm just beginning to learn python. I wrote an example script to test OOP in python, but something very odd has happened. When I call a class method, Python is calling the function with one more parameter than given.
Here is the code:
1. class Bar:
2. num1,num2 = 0,0
3. d开发者_Go百科ef __init__(num1,num2):
4. num1,num2 = num1,num2
5. def foo():
6. if num1 > num2:
7. print num1,'is greater than ',num2,'!'
8. elif num1 is num2:
9. print num1,' is equal to ',num2,'!'
10. else:
11. print num1,' is less than ',num2,'!'
12. a,b = 42,84
13. t = Bar(a,b)
14. t.foo
15.
16. t.num1 = t.num1^t.num2
17. t.num2 = t.num2^t.num1
18. t.num1 = t.num1^t.num2
19.
20. t.foo
And the error message I get:
python test.py
Traceback (most recent call last):
File "test.py", line 13, in
t = Bar(a,b)
TypeError: init() takes exactly 2 arguments (3 given)
Can anyone help?
Thanks in advanceThe first argument passed to an instance method is the instance itself. Typically this is called self
when defining the function:
def __init__(self, num1, num2):
Consider reading the tutorial.
Couple things:
- Your class is named
Bar
but you're calling it asbar(a, b)
. Change that toBar(a, b)
to solve this problem. - Classes need to inherit from something (if nothing, then
object
). You needclass Bar(object):
- Instance methods, in Python, are always supplied one parameter, which is the object itself, before other passed parameters. So your
def __init__(num1, num2):
should bedef __init__(self, num1, num2):
, and the same fordef foo()
. - All of your instance variables need to be prefixed by
self.
. Sonum1
should beself.num1
, etc. - The
^
operator is boolean XOR. Not sure if this is what you want, it's often confused with the power operator,**
.
Here's your example, cleaned up and fixed accordingly:
class Bar(object):
num1, num2 = 0, 0
def __init__(self, num1, num2):
self.num1, self.num2 = num1, num2
def foo(self):
if self.num1 > self.num2:
print self.num1,'is greater than ',self.num2,'!'
elif self.num1 is self.num2:
print self.num1,' is equal to ',self.num2,'!'
else:
print self.num1,' is less than ',self.num2,'!'
a, b = 42, 84
t = Bar(a, b)
t.foo()
t.num1 = t.num1 ^ t.num2
t.num2 = t.num2 ^ t.num1
t.num1 = t.num1 ^ t.num2
t.foo()
And the result:
42 is less than 84 !
84 is greater than 42 !
a) By convention, the first parameter of a method is called self.
b) On line 4 you are self-assigning. Maybe you want to say self.num1, self.num2
c) If you want to call the method foo of t (lines 14 and 20) you should add parentheses at the end: t.foo()
d) The indentation is idiomatically given by 4 spaces, which makes reading much easier.
EDIT: You might want to look at chapters 15-18 of Allen Downey's book "Think Python: How to Think Like a Computer Scientist". This book is very short, nicely written, and easy to read. It is freely available here.
EDIT2: I hadn't noticed this before, but as dash-tom-bang pointed out in a comment below, in this context it is best if (on line 8) you compared for equality using == instead of is.
In regards to that particular error message, you're missing the self
argument on line 3. It should read:
def __init__(self, num1,num2):
Unlike instance methods in other OOP languages, in Python, you have to explicitly name the instance as the first argument when defining such a method. Then, when you call obj.some_method()
, obj
is automatically and implicitly passed as the first argument to some_method
.
The first argument is idiomatically named self
, but nothing is stopping you from naming it anything else.
Python identifiers are case-sensitive... bar != Bar...
Also, you need to explicitly declare self as the first argument of the __init__()
method, something like:
def __init__(self, num1, num2):
#...etc.
BTW, see bcherry's answer as he/she covers other typical Python beginner mistakes (such as not explicitly prefixing the instance variables with self.
...
精彩评论