Q:

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.   def __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 advance

A:

The 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.

A:

Couple things:

Your class is named Bar but you're calling it as bar(a, b).  Change that to Bar(a, b) to solve this problem.
Classes need to inherit from something (if nothing, then object).  You need class 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 be def __init__(self, num1, num2):, and the same for def foo().
All of your instance variables need to be prefixed by self..  So num1 should be self.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:

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.

