How do I properly use a function under a class?

Viewed 1640

I am currently learning Python. Since I am a big fan of OO (object-oriented) programming, obviously it's not hard to apply it in Python. But when I tried it, it seems very different to C#.

As you can see below, I am trying to create a character class, with three attributes Id, Hp, and Mana. The score is calculated by adding up Hp and Mana and then times 10.

As you can see, after defining MyChar where id=10 hp=100 mana=100, I was expecting MyChar.Score is (100+100)*10, which is 2000, but weirdly, it says:

bound method Character.Score of <__main__.Character object at 0x0000021B17DD1F60> as the result of print(MyChar.Score).

How can I fix this problem?

Here is my code:

class Character:

    def __init__(self, Id, Hp, Mana):
        self.Id = Id;
        self.Hp = Hp;
        self.Mana = Mana;


    def Score(self):
        return (self.Hp + self.Mana)*10;

MyChar = Character(10, 100, 100);

print(MyChar.Score)
4 Answers

If you want to use it like a property in C#, decorate the function with @property, like so:

class Character:

    def __init__(self,Id,Hp,Mana):
        self.Id=Id;
        self.Hp=Hp;
        self.Mana=Mana;

    @property
    def Score(self):
        return (self.Hp+self.Mana)*10;

MyChar=Character(10,100,100);

print(MyChar.Score)

So you don't have to call it like a function.

For more advanced usage of properties (e.g. also having a setter func), see the official docs: https://docs.python.org/3/library/functions.html#property

tl;dr

Use it like any other function by calling it: print(MyChar.Score()) (note the additional pair of parentheses).


As you've correctly stated, MyChar.Score is a "function under a class" (aka "method"). So just use it like any other function by calling it: suffixing it with a pair of parentheses.

print(MyChar.Score())
#                 ^^

Without the call, simply doing print(MyChar.Score) prints <bound method blah blah>, i.e. the informal string representation of the method. The print function internally calls __str__() magic method (or __repr__(), if the former isn't defined). Hence, the following print equivalent lines:

print(MyChar.Score.__str__())
print(str(MyChar.Score))
print(MyChar.Score.__repr__())
print(repr(MyChar.Score))

In Python, functions are first-class citizens, hence they are objects and have the __str__() and __repr__() methods.

In Python, everything is an object, including classes, functions and methods, so MyChar.Score (without the parens) only resolves the Score attribute on MyChar object. This yields a method object, which happens to be a callable object (an object that implements the __call__ special method). You then have to apply the call operator (the parens) to actually call it.

You may want to check the official documentation for more on Python's object model.

class Character(object):
    def __init__(self):
        print ('Starting')

    def method(self):
        print ('This is a method()')
ch = Character()
'''When we don't add the bracket after the method call, it would lead to a method bound error as in your case'''
print (ch.method)
'''This can be solved by doing the following line'''
ch.method()
Related