On Sun, Aug 11, 2019 at 10:58:37PM -0500, James Hartley wrote:
> I am lacking in understanding of the @staticmethod property.
> Explanation(s)/links might be helpful.  I have not found the descriptions
> found in the Internet wild to be particularly instructive.  Given the code
> below:
[...]
> The class method Foo.dimensions() is capable of accessing class members,
> but Foo.dimensions1() cannot. What does the @staticmethod decorator really
> add?

Very little.

To understand staticmethod in Python, you have to understand what 
ordinary methods do.

When you make a class with a method:

class MyClass(object):
    def spam(self):
        print(self)


the interpreter creates a plain old regular function called "spam", and 
attaches it to MyClass. It is precisely the same as doing this:

def spam(self):
    print(self)

class MyClass(object):
    pass

MyClass.spam = spam

except more convenient. Methods are actually regular functions under 
the hood. But when you access a method, like this:

instance = MyClass()
instance.spam()  # call the method

the interpreter does some runtime magic to convert the function object 
into a method object which automatically knows what "self" is. This 
magic is called "the descriptor protocol", it's very clever but advanced 
programming, and the details aren't important here.

So just think of it like this:

When you access instance.spam, the interpreter converts the plain old 
dumb function object which has no idea what "self" is into a magical 
method object which does.

If you bypass the descriptor "magic", you can grab hold of the plain-old 
regular function:

py> instance = MyClass()
py> vars(type(instance))['spam']  # Bypass all the magic.
<function MyClass.spam at 0xb78433d4>

but it's dumb, and doesn't know what "self" is:

py> vars(type(instance))['spam']()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: spam() missing 1 required positional argument: 'self'


If you use normal attribute access, the function is turned into a method 
object that knows what "self" should be:

py> instance.spam  # Normal access.
<bound method MyClass.spam of <__main__.MyClass object at 0xb77e52ac>>

py> instance.spam()  # "self" is automatically provided
<__main__.MyClass object at 0xb77e52ac>


So that's how methods work normally. But what if you don't want a method 
that understands "self", but a regular dumb-old function, but for some 
reason it needs to be attached to a class?

You can't use a regular function in the class body, because it will be 
automatically turned into a method on access, and for some reason you 
don't want that. You need a way to tell the interpreter "Don't convert 
this into a method with self, leave it as a regular function", and 
staticmethod is that way.

(To be pedantic, it doesn't actually leave it as a regular function, it 
converts it to a staticmethod object which behaves like a regular 
function. But that's a difference which normally makes no difference.)

So you can see, the niche for staticmethod is very, very narrow. You 
need something that is attached to a class, which you can call like a 
method, but you don't want it to receive "self" as the automatic first 
argument. That's pretty rare.

For a very long time, the only known use for staticmethod was in the 
tests checking that the staticmethod code worked correctly.

So that's what staticmethod does. It is occassionally useful, but not 
very often. Chances are, if you think you need one, you probably don't.

So why doesn't it work the way you expect? For that, read my next email.




-- 
Steven
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to