3

Let us consider the following example:

class X:
    def run(self):
        print("An example.")

X().run()

The output is:

> An example.

But when we omit the reference to the instance:

class X:
    def run():
        print("An example.")

X().run()

The output is:

TypeError: run() takes 0 positional arguments but 1 was given

When we instantiate the class, __ new __ gets called and the instance is created, ok. But how it requires an instance without defining __ init __? (I'm surprised because, I've always written __ init __ thinking that it was responsible for defining the convention / self name for referencing the variable). I'm confused.

Ericson Willians
  • 7,606
  • 11
  • 63
  • 114
  • well, `X().run()` calls `run(object_ref)` where `object_ref` is your old `self` – Pynchia Sep 18 '15 at 05:46
  • in case `self` is not needed, you can decorate the method with `@staticmethod`. See if [this SO QA](http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python) helps shed some light on the subject of static and class methods – Pynchia Sep 18 '15 at 05:50
  • I'd recommend to start using new-style classes. Please read [this SO QA](http://stackoverflow.com/questions/54867/what-is-the-difference-between-old-style-and-new-style-classes-in-python) on the subject – Pynchia Sep 18 '15 at 05:58
  • 1
    @Pynchia: from the parentheses in the `print` calls, I'd guess that this is Python 3, so `X` *is* a new-style class. – Mark Dickinson Sep 18 '15 at 06:01
  • Nah, \__init__ is just there to initialize stuff on the class. If there is no \__init__, then object.\__init__ will get called and it has only parameter, self. This will lead to errors is you have myClass(somevar=1) but you forgot to define an \__init__(self, somevar). But Python is not Java (or other languages) and you don't need to define init if you don't want to. Nor do you have call the ancestor's init. All remarks by alfasin are strictly correct. – JL Peyret Sep 18 '15 at 06:17
  • Finally you create a method **def __init__(this)** if you were really fond of javascript and did not mind annoying **everyone** - there is nothing magic about *self* as a name for the instance variable being passed as the first parameter, it's just a convention. – JL Peyret Sep 18 '15 at 06:19
  • For `instance = X()`, `instance.run()` is the same as `X.run(instance)`. – Peter Wood Sep 18 '15 at 06:38

1 Answers1

2

When you call instance.run() if implicitly calls run(instance) which is why you're receiving the error:

TypeError: run() takes 0 positional arguments but 1 was given

That's also the reason why instance methods should have self as the first argument.

Second, you're using the old way of declaring a class - class X:
The new way1 is class X(object): but regardless if you're using the new/old annotation, the call X() will return an instance of the class, even in case you didn't define __init__.

And third, if you want to make it a class method you can either do what Pynchia suggested in the comment above (annotate the method with @staticmethod) or declare the method as a class method by specifying that the first argument is cls and annotating it as a class-method:

class X:

    @classmethod
    def run(cls):
        print "a"


X.run()  # prints a

1. According to Mark's comment below, in Python 3 we return to the "old way" of declaring a class. Good to know - thanks Mark!

Mazdak
  • 105,000
  • 18
  • 159
  • 188
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • 1
    To declare the method as a class method, use `@classmethod` decorator, using `cls` name alone does not change anything. – bereal Sep 18 '15 at 05:54
  • 3
    `class X(object):` is the *old* new way of declaring a class! For Python 3, `class X:` is just fine. – Mark Dickinson Sep 18 '15 at 06:02
  • @MarkDickinson seriously? we're not very deterministic in our (Python) community, are we ? :))) – Nir Alfasi Sep 18 '15 at 06:06
  • @MarkDickinson thanks - the answer has been updated! – Nir Alfasi Sep 18 '15 at 06:08
  • You may get new-style behaviour out of python 3 with an old-style class declaration, but it's still not good code because (a) it may create unnecessary problems for someone trying to backport to Python 2, and (b) the Zen of Python "explicit is better than implicit". – nigel222 Sep 18 '15 at 09:39
  • @nigel222 "explicit is better than implicit" is true for *any* programming language (and other stuff as well). :) – Nir Alfasi Sep 18 '15 at 14:42