d9h
d9h

Reputation: 89

Difference between calling method with self and with class name?

class A:

    def __init__(self, text):
        self.printStats()
        A.printStats(text)

    def printStats(self):
        print(self)

a = A("Hello")

This prints:

<A object at 0x7f47e2f08ac8>
Hello

Why is this (A.printStats(text)) possible? I understand what is happening (self references text), but I don't understand why.

Upvotes: 5

Views: 1773

Answers (3)

Moses Koledoye
Moses Koledoye

Reputation: 78564

Your code would fail in Python 2 as calling a method via the class requires that the first argument of the class is actually an instance of the class.

In Python 3, the implementation is less stricter as the first argument is only expected to implement the required interface pertaining to an instance of the class; no check on whether the parameter is an instance is performed. And since you're not actually accessing any instance method/variable inside printStats via self this works and it simply prints the passed string 'hello'.

Upvotes: 1

Piotr Dabkowski
Piotr Dabkowski

Reputation: 5939

When you create an instance of the class:

a = A('some text')

The self argument becomes permanently bound to a, this is the magic behind classes. If you try a.printStats('something') this will raise an error as self argument is already occupied by a. You can recover the original function that has unbound self with a.printFunction.__func__. Try a.printFunction.__func__('this will be self argument')

However, when you don't create an instance there is nothing to bind self to so self is still available for use. In such case you can treat A as a simple dictionary holding functions.

A = {'__init__': someInitFunction,
     'printStats': printStatsFunction}

You have to remember that the name self is arbitrary and you can use any word instead, even not_self.

Upvotes: 1

noɥʇʎԀʎzɐɹƆ
noɥʇʎԀʎzɐɹƆ

Reputation: 10667

A.printStats(text)

does NOT call printStats with an instance of A. It calls it with a string - no self is passed.

def printStats(self):
    # <--- here, "self" if the string "Hello", not an instance of A.
    print(self)

A.printStats(self) is equivalent to self.printStats. Likewise if you have a function printStatsWithPrefix;

class A:
    def printStatsWithPrefix(self, prefix):
        ...  # function body goes here

you'd have to do A.printStatsWithPrefix(self, prefix).


A note on style: By Python convention (PEP 8), you should use lowercase_with_underscores for function names.

Upvotes: 5

Related Questions