1

Just recently I noticed a new concept: class function in python3.

(NOTE: not ask class method, but class function like fun in next code.)

class A:
    def fun():
        print("fun")

    @staticmethod
    def fun2():
        print("fun2")

A.fun()
A.fun2()

# updated
print(A.__dict__)
# {'__module__': '__main__', 'fun': <function A.fun at 0x0000014C658F30D0>, 'fun2': <staticmethod object at 0x0000014C658E1C50>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}    

If execute above code:

python2 output:

Traceback (most recent call last): File "a.py", line 9, in
A.fun() TypeError: unbound method fun() must be called with A instance as first argument (got nothing instead)

python3 output:

fun
fun2

And, in python3, it seems been called as class function, it's no longer a method.

So, my question is: why this changes? As we could already define some utility function in class using @staticmethod.

entropy
  • 840
  • 6
  • 16
atline
  • 28,355
  • 16
  • 77
  • 113
  • Of course, I can still use staticmethod, just I'm afraid I will miss some new feature just like the old question about the compare for "class method & static method". Finally, we all know we can use class method to create factory methods which static method can't. So how will be this compare now? – atline Mar 15 '19 at 09:00
  • 1
    Possible duplicate of [Why can instance methods be called as class methods in Python 3?](https://stackoverflow.com/questions/48103889/why-can-instance-methods-be-called-as-class-methods-in-python-3) – snakecharmerb Mar 15 '19 at 09:19

1 Answers1

1

This is because all functions in python 3 classes have static behaviour by default. Python 3 drops the concept of unbound methods. All member methods of a class can be called using the class object itself, as you have done.

Therefore, in addition to your code, this code is permitted too:

class A:
    def func(self):
        print('Hello')

A.func(123)

This was possibly done for convenience, saving you from having to write @staticmethod in some cases, and also to let you reuse instance methods with other types of objects, as you see in the above snippet.

The function is not shown as a staticmethod, because it isn't. A parameter-less static method can still be called on an instance of the class, as @Aran-Fey pointed out, and that is why we have @staticmethod in Python 3.

(Please check the edit history for the older, incorrect version of this answer)

entropy
  • 840
  • 6
  • 16
  • Seems reasonable, but see update, I print the dict of this class. If just for convenience, why `fun`'s type is not `staticmethod`? Could you share some link I can reference which can prove your idea? – atline Mar 15 '19 at 08:51
  • Edited :). Unfortunately, I cannot find any documentation to back this up. – entropy Mar 15 '19 at 09:06
  • Ok, I upvote this answer because seems reasonable, wait for a more time to see if any official document suggested by others. If no, will accept this answer thanks. – atline Mar 15 '19 at 09:08
  • 2
    parameterless functions in python 3 classes are not `staticmethods` by default.. can you include a code example where you show what you mean? – Arne Mar 15 '19 at 09:28
  • Yes, they aren't, and I have explained why they cannot be – entropy Mar 15 '19 at 09:31
  • 3
    *"If no self parameter is specified, it effectively makes the function the same as a static method."* False. `A().fun()` will throw an exception, but `A().fun2()` will not. *"The decorator @staticmethod likely hasn't been removed for backwards compatibility reasons."* Wrong again. It hasn't been removed because it has a purpose. – Aran-Fey Mar 15 '19 at 09:31
  • @Aran-Fey, I also notice the call with `A()`. And in the duplicate suggestion, it said: `The concept of “unbound methods” has been removed from the language. When referencing a method as a class attribute, you now get a plain function object.` So, this means it is just `a plain function object`, does this mean it's just like a function out of class? Nothing related with the class A? – atline Mar 15 '19 at 09:40
  • @lagom That's a little difficult to answer. It's true that there's no difference between a function defined in a class and a function defined outside of a class. *But* you have to keep in mind that all functions are [descriptors](https://docs.python.org/3/glossary.html#term-descriptor), which makes them behave differently if accessed through an instance (like `A().fun()`). All it means is that if you define a function outside of a class and then add it to the class (like `A.fun3 = fun3`), it'll act exactly the same as if it had been defined in the class all along. – Aran-Fey Mar 15 '19 at 09:48
  • 1
    @Aran-Fey But what purpose does having `@staticmethod` serve in python3? Is it only to allow invocation through class instances? – entropy Mar 15 '19 at 09:50
  • @suicidalteddy Yes, that's really it. – Aran-Fey Mar 15 '19 at 09:53
  • @Aran-Fey If that's the case, I will research this some more and edit the answer to provide correct information – entropy Mar 15 '19 at 10:00
  • @Aran-Fey Corrected my answer – entropy Mar 15 '19 at 11:00