Are there more than three types of methods in Python?
methods, python
Solution
Some background: In Python 2, "regular" instance methods could give rise to two kinds of method objects, depending on whether you accessed them via an instance or the class. If you did `inst.meth` (where `inst` is an instance of the class), you got a bound method object, which keeps track of which instance it is attached to, and passes it as `self`. If you did `Class.meth` (where `Class` is the class), you got an unbound method object, which had no fixed value of `self`, but still did a check to make sure a `self` of the appropriate class was passed when you called it.
In Python 3, unbound methods were removed. Doing `Class.meth` now just gives you the "plain" function object, with no argument checking at all.
Was making a method this way intentional in Python 3's design?
If you mean, was removal of unbound methods intentional, the answer is yes. You can see discussion from Guido on the mailing list. Basically it was decided that unbound methods add complexity for little gain.
Among the classic method types, what type of method is unknown_mthd?
It is an instance method, but a broken one. When you access it, a bound method object is created, but since it accepts no arguments, it's unable to accept the `self` argument and can't be successfully called.
Why can unknown_mthd be called by the class without passing an argument?
In Python 3, unbound methods were removed, so `Test.unkown_mthd` is just a plain function. No wrapping takes place to handle the `self` argument, so you can call it as a plain function that accepts no arguments. In Python 2, `Test.unknown_mthd` is an unbound method object, which has a check that enforces passing a `self` argument of the appropriate class; since, again, the method accepts no arguments, this check fails.
Problem
I understand there are at least 3 kinds of methods in Python having different first arguments: - instance method - instance, i.e. `self` - class method - class, i.e. `cls` - static method - nothing These classic methods are implemented in the `Test` class below including an usual method: ``` class Test(): def __init__(self): pass def instance_mthd(self): print("Instance method.") @classmethod def class_mthd(cls): print("Class method.") @staticmethod def static_mthd(): print("Static method.") def unknown_mthd(): # No decoration --> instance method, but # No self (or cls) --> static method, so ... (?) print("Unknown method.") ``` In Python 3, the `unknown_mthd` can be called safely, yet it raises an error in Python 2: ``` >>> t = Test() >>> # Python 3 >>> t.instance_mthd() >>> Test.class_mthd() >>> t.static_mthd() >>> Test.unknown_mthd() Instance method. Class method. Static method. Unknown method. >>> # Python 2 >>> Test.unknown_mthd() TypeError: unbound method unknown_mthd() must be called with Test instance as first argument (got nothing instead) ``` This error suggests such a method was not intended in Python 2. Perhaps its allowance now is due to the elimination of unbound methods in Python 3 (REF 001). Moreover, `unknown_mthd` does not accept args, and it can be bound to called by a class like a staticmethod, `Test.unknown_mthd()`. However, it is not an explicit staticmethod (no decorator). Questions - Was making a method this way (without args while not explicitly decorated as staticmethods) intentional in Python 3's design? UPDATED - Among the classic method types, what type of method is `unknown_mthd`? - Why can `unknown_mthd` be called by the class without passing an argument? Some preliminary inspection yields inconclusive results: ``` >>> # Types >>> print("i", type(t.instance_mthd)) >>> print("c", type(Test.class_mthd)) >>> print("s", type(t.static_mthd)) >>> print("u", type(Test.unknown_mthd)) >>> print() >>> # __dict__ Types, REF 002 >>> print("i", type(t.__class__.__dict__["instance_mthd"])) >>> print("c", type(t.__class__.__dict__["class_mthd"])) >>> print("s", type(t.__class__.__dict__["static_mthd"])) >>> print("u", type(t.__class__.__dict__["unknown_mthd"])) >>> print() i <class 'method'> c <class 'method'> s <class 'function'> u <class 'function'> i <class 'function'> c <class 'classmethod'> s <class 'staticmethod'> u <class 'function'> ``` The first set of type inspections suggests `unknown_mthd` is something similar to a staticmethod. The second suggests it resembles an instance method. I'm not sure what this method is or why it should be used over the classic ones. I would appreciate some advice on how to inspect and understand it better. Thanks. - REF 001: What's New in Python 3: “unbound methods” has been removed - REF 002: How to distinguish an instance method, a class method, a static method or a function in Python 3? - REF 003: What's the point of @staticmethod in Python?