I'm trying to understand how descriptors work in python. I got the big picture, but I have problems understanding the @staticmethod decorator.
The code I'm referring to specifically is from the corresponding python doc: https://docs.python.org/3/howto/descriptor.html
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
return types.MethodType(self, obj)
class StaticMethod(object):
"Emulate PyStaticMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return self.f
My question is: When self.f
is accessed in the last line, doesn't f
get recognized as a descriptor itself (because every function is a non-data descriptor) and thus gets bound to self, which is a StaticMethod object?
Static methods can be used to group similar utility methods under the same class. For methods within a class, you either need to add self as the first argument or decorate the method with @staticmethod . "Non-decorated methods" without arguments will raise an error.
Class method can access and modify the class state. Static Method cannot access or modify the class state. The class method takes the class as parameter to know about the state of that class. Static methods do not know about class state.
A static method can be called from either a class or object reference. We can call it Utils if foo() is a static function in Class Utils. Utils. foo() as well as Utils().
A class method is a method which is bound to the class and not the object of the class. They have the access to the state of the class as it takes a class parameter that points to the class and not the object instance. It can modify a class state that would apply across all the instances of the class.
Descriptors are class attributes and hence need to be defined at the class level.
The function f
in the last example is an instance attribute, as set inside __init__
by binding to attribute named f
to the input object referred by f
. As it is not a class attribute, it will never be classified as a descriptor.
Now, from the caller's perspective, staticmethod
is a class attribute as it is implemented at the class level e.g. like:
class Foo:
@staticmethod
def bar():
return 10
the decorator is only a syntactic sugar, you can very well write like:
class Foo:
def bar():
return 10
bar = staticmethod(bar)
so it will be treated as a descriptor in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With