When should a static method be a function? - python

I am writing a class for an image processing algorithm which has some methods, and notably a few static methods. My IDE keeps telling me to convert static methods to function which leads me to the following question:
When should a static method be turned into a function? When shouldn't it?

There are no set rules in python regarding this decision, but there are style-guides defined e.g. by companies that look to solve the ambiguity of when to use what. One popular example of this would be the Google Python Style Guide:
Never use staticmethod unless forced to in order to integrate with an API defined in an existing library. Write a module level function instead.
My guess is, that your IDE follows this stance of a hard no against the staticmethod. If you decide, that you still want to use staticmethods, you can try to disable the warning by adding # noqa as a comment on the line where the warning is shown. Or you can look in your IDE for a setting to disable this kind of warning globally.
But this is only one opinion. There are some, that do see value in using staticmethods (staticmethod considered beneficial, Why Python Developers Should Use #staticmethod and #classmethod), and there are others that argue against the usage of staticmethods (Thoughts On #staticmethod Usage In Python, #staticmethod considered a code smell)
Another quote that is often cited in this discussion is from Guido van Rossum (creator of Python):
Honestly, staticmethod was something of a mistake -- I was trying to
do something like Java class methods but once it was released I found
what was really needed was classmethod. But it was too late to get rid
of staticmethod.
I have compiled a list of arguments that I found, without any evaluation or order.
Pro module-level function:
Staticmethod lowers the cohesion of the class it is in as it is not using any of the attributes the class provides.
To call the staticmethod any other module needs to import the whole class even if you just want to use that one method.
Staticmethod binds the method to the namespace of the class which makes it longer to write SomeWhatDescriptiveClassName.method instead of method and more work to refactor code if you change the class.
Easier reuse of method in other classes or contexts.
The call signature of a staticmethod is the same as that of a classmethod or instancemethod. This masks the fact that the staticmethod does not actually read or modify any object information especially when being called from an instance. A module-level function makes this explicit.
Pro staticmethod:
Being bound by an API your class has to work in, it can be the only valid option.
Possible usage of polymorphism for the method. Can overwrite the staticmethod in a subclass to change behaviour.
Grouping a method directly to a class it is meant to be used with.
Easier to refactor between classmethod, instancemethod and staticmethod compared to module-level functions.
Having the method under the namespace of the class can help with reducing possible namespace-collisions inside your module and reducing the namespace of your module overall.
As I see it, there are no strong arguments for or against the staticmethod (except being bound by an API). So if you work in an organisation that provides a code standard to follow, just do that. Else it comes down to what helps you best to structure your code for maintainability and readability, and to convey the message of what your code is meant to do and how it is meant to be used.

Related

Python method call syntax shorthand

Is there a reason we call methods in python like object.method instead of Class.method(object)?
Maybe it isn't a strange choice, but personally it made understanding the self parameter much easier when I was shown the second way of calling a method.
Hardcoding the class name basically prevents you from using polymorphism. This is general OOP, not particularly a Python feature.
Your calling code should not need to know, nor care, which exact class object is.
This is immediately a problem for code where object can be a member of either Baseclass or Derivedclass, but much more complex inheritance and method overriding scenarios are possible, and sometimes necessary.

Advantages of using static methods over instance methods in python

My IDE keeps suggesting I convert my instance methods to static methods. I guess because I haven't referenced any self within these methods.
An example is :
class NotificationViewSet(NSViewSet):
def pre_create_processing(self, request, obj):
log.debug(" creating messages ")
# Ensure data is consistent and belongs to the sending bot.
obj['user_id'] = request.auth.owner.id
obj['bot_id'] = request.auth.id
So my question would be: do I lose anything by just ignoring the IDE suggestions, or is there more to it?
This is a matter of workflow, intentions with your design, and also a somewhat subjective decision.
First of all, you are right, your IDE suggests converting the method to a static method because the method does not use the instance. It is most likely a good idea to follow this suggestion, but you might have a few reasons to ignore it.
Possible reasons to ignore it:
The code is soon to be changed to use the instance (on the other hand, the idea of soon is subjective, so be careful)
The code is legacy and not entirely understood/known
The interface is used in a polymorphic/duck typed way (e.g. you have a collection of objects with this method and you want to call them in a uniform way, but the implementation in this class happens to not need to use the instance - which is a bit of a code smell)
The interface is specified externally and cannot be changed (this is analog to the previous reason)
The AST of the code is read/manipulated either by itself or something that uses it and expects this method to be an instance method (this again is an external dependency on the interface)
I'm sure there can be more, but failing these types of reasons I would follow the suggestion. However, if the method does not belong to the class (e.g. factory method or something similar), I would refactor it to not be part of the class.
I think that you might be mixing up some terminology - the example is not a class method. Class methods receive the class as the first argument, they do not receive the instance. In this case you have a normal instance method that is not using its instance.
If the method does not belong in the class, you can move it out of the class and make it a standard function. Otherwise, if it should be bundled as part of the class, e.g. it's a factory function, then you should probably make it a static method as this (at a minimum) serves as useful documentation to users of your class that the method is coupled to the class, but not dependent on it's state.
Making the method static also has the advantage this it can be overridden in subclasses of the class. If the method was moved outside of the class as a regular function then subclassing is not possible.

Static classes in Python

I once read (I think on a page from Microsoft) that it's a good way to use static classes, when you don't NEED two or more instances of a class.
I'm writing a program in Python. Is it a bad style, if I use #classmethod for every method of a class?
Generally, usage like this is better done by just using functions in a module, without a class at all.
It's terrible style, unless you actually need to access the class.
A static method [...] does not translate to a Python classmethod. Oh sure, it results in more or less the same effect, but the goal of a classmethod is actually to do something that's usually not even possible [...] (like inheriting a non-default constructor). The idiomatic translation of a [...] static method is usually a module-level function, not a classmethod or staticmethod.
source
In my experience creating a class is a very good solution for a number of reasons. One is that you wind up using the class as a 'normal' class (esp. making more than just one instance) more often than you might think. It's also a reasonable style choice to stick with classes for everthing; this can make it easier for others who read/maintain your code, esp if they are very OO - they will be comfortable with classes. As noted in other replies, it's also reasonable to just use 'bare' functions for the implementation. You may wish to start with a class and make it a singleton/Borg pattern (lots of examples if you googlefor these); it gives you the flexibility to (re)use the class to meet other needs. I would recommend against the 'static class' approach as being non-conventional and non-Pythonic, which makes it harder to read and maintain.
There are a few approaches you might take for this. As others have mentioned, you could just use module-level functions. In this case, the module itself is the namespace that holds them together. Another option, which can be useful if you need to keep track of state, is to define a class with normal methods (taking self), and then define a single global instance of it, and copy its instance methods to the module namespace. This is the approach taken by the standard library "random" module -- take a look at lib/python2.5/random.py in your python directory. At the bottom, it has something like this:
# Create one instance, seeded from current time, and export its methods
# as module-level functions. [...]
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
...
Or you can take the basic approach you described (though I would recommend using #staticmethod rather than #classmethod in most cases).
You might actually want a singleton class rather than a static class:
Making a singleton class in python

Decorators versus inheritance

How do you decide between using decorators and inheritance when both are possible?
E.g., this problem has two solutions.
I'm particularly interested in Python.
Decorators...:
...should be used if what you are trying to do is "wrapping". Wrapping consists of taking something, modifying (or registering it with something), and/or returning a proxy object that behaves "almost exactly" like the original.
...are okay for applying mixin-like behavior, as long as you aren't creating a large stack of proxy objects.
...have an implied "stack" abstraction:
e.g.
#decoA
#decoB
#decoC
def myFunc(...): ...
...
Is equivalent to:
def myFunc(...): ...
...
myFunc = decoA(decoB(decoC(myFunc))) #note the *ordering*
Multiple inheritance...:
... is best for adding methods to classes; you cannot use it to decorate functions easily. In this context, it can be used to achieve mixin-like behavior if all you need is a set of "duck-typing style" extra methods.
... may be a bit unwieldy if your problem is not a good match for it, with issues with superclass constructors, etc. For example, the subclasses __init__ method will not be called unless it is called explicitly (via the method-resolution-order protocol)!
To sum up, I would use decorators for mixin-like behavior if they didn't return proxy objects. Some examples would include any decorator which returns the original function, slightly modified (or after registering it somewhere or adding it to some collection).
Things you will often find decorators for (like memoization) are also good candidates, but should be used in moderation if they return proxy objects; the order they are applied matter. And too many decorators on top of one another is using them in a way they aren't intended to be used.
I would consider using inheritance if it was a "classic inheritance problem", or if all I needed for the mixin behavior were methods. A classic inheritance problem is one where you can use the child wherever you could use the parent.
In general, I try to write code where it is not necessary to enhance arbitrary things.
The problem you reference is not deciding between decorators and classes. It is using decorators, but you have the option of using either:
a decorator, which returns a class
a decorator, which returns a function
A decorator is just a fancy name for the "wrapper" pattern, i.e. replacing something with something else. The implementation is up to you (class or function).
When deciding between them, it's completely a matter of personal preference. You can do everything you can do in one with the other.
if decorating a function, you may prefer decorators which return proxy functions
if decorating a class, you may prefer decorators which return proxy classes
(Why is it a good idea? There may be assumptions that a decorated function is still a function, and a decorated class is still a class.)
Even better in both cases would be to use a decorator which just returns the original, modified somehow.
edit: After better understanding your question, I have posted another solution at Python functools.wraps equivalent for classes
The other answers are quite great, but I wanted to give a succinct list of pros and cons.
The main advantage of mixins is that the type can be checked at runtime using isinstance and it can be checked with linters like MyPy. Like all inheritance, it should be used when you have an is-a relationship. For example dataclass should probably have been a mixin in order to expose dataclass-specific introspection variables like the list of dataclass fields.
Decorators should be preferred when you don't have an is-a relationship. For example, a decorator that propagates documentation from another class, or registers a class in some collection.
Decoration typically only affects the class it decorates, but not classes that inherit from the base class:
#decorator
class A:
... # Can be affected by the decorator.
class B(A):
... # Not affected by the decorator in most cases.
Now that Python has __init_subclass__, everything that decorators can do can be done with mixins, and they typically do affect child subclasses:
class A(Mixin):
... # Is affected by Mixin.__init_subclass__.
class B(A):
... # Is affected by Mixin.__init_subclass__.
Mixins have another advantage, which is that they can provide empty base class methods. Child classes can override these methods with some "augmenting" behavior, and then call super. The decorator cannot easily provide such base class methods. This is another way in which mixins are more flexible.
In summary, the questions you should ask when deciding between a mixin and decoration are:
Is there an is-a pattern?
Would you ever call isinstance?
Would you use the mixin in a type annotation?
Do you want the behavior to affect child classes?
Do you need augmenting methods?
In general, lean towards inheritance.
If both are equivalent, I would prefer decorators, since you can use the same decorator for many classes, while inheriting apply to only one specific class.
Personally, I would think in terms of code reuse. Decorator is sometimes more flexible than inheritance.
Let's take caching as an example. If you want to add caching facility to two classes in your system: A and B, with inheritance, you'll probably wind up having ACached and BCached. And by overriding some of the methods in these classes, you'll probably duplicate a lot of codes for the same caching logic. But if you use decorator in this case, you only need to define one decorator to decorate both classes.
So, when deciding which one to use, you may first want to check if the extended functionality is only specific to this class or if the same extended functionality can be reused in other parts of your system. If it cannot be reused, then inheritance should probably do the job. Otherwise, you can think about using decorator.

When is using __call__ a good idea?

What are peoples' opinions on using the __call__. I've only very rarely seen it used, but I think it's a very handy tool to use when you know that a class is going to be used for some default behaviour.
I think your intuition is about right.
Historically, callable objects (or what I've sometimes heard called "functors") have been used in the OO world to simulate closures. In C++ they're frequently indispensable.
However, __call__ has quite a bit of competition in the Python world:
A regular named method, whose behavior can sometimes be a lot more easily deduced from the name. Can convert to a bound method, which can be called like a function.
A closure, obtained by returning a function that's defined in a nested block.
A lambda, which is a limited but quick way of making a closure.
Generators and coroutines, whose bodies hold accumulated state much like a functor can.
I'd say the time to use __call__ is when you're not better served by one of the options above. Check the following criteria, perhaps:
Your object has state.
There is a clear "primary" behavior for your class that's kind of silly to name. E.g. if you find yourself writing run() or doStuff() or go() or the ever-popular and ever-redundant doRun(), you may have a candidate.
Your object has state that exceeds what would be expected of a generator function.
Your object wraps, emulates, or abstracts the concept of a function.
Your object has other auxilliary methods that conceptually belong with your primary behavior.
One example I like is UI command objects. Designed so that their primary task is to execute the comnand, but with extra methods to control their display as a menu item, for example, this seems to me to be the sort of thing you'd still want a callable object for.
Use it if you need your objects to be callable, that's what it's there for
I'm not sure what you mean by default behaviour
One place I have found it particularly useful is when using a wrapper or somesuch where the object is called deep inside some framework/library.
More generally, Python has a lot of double-underscore methods. They're there for a reason: they are the Python way of overloading operators. For instance, if you want a new class in which addition, I don't know, prints "foo", you define the __add__ and __radd__ methods. There's nothing inherently good or bad about this, any more than there's anything good or bad about using for loops.
In fact, using __call__ is often the more Pythonic approach, because it encourages clarity of code. You could replace MyCalculator.calculateValues( foo ) with MyCalculator( foo ), say.
Its usually used when class is used as function with some instance context, like some DecoratorClass which would be used as #DecoratorClass('some param'), so 'some param' would be stored in the instance's namespace and then instance being called as actual decorator.
It is not very useful when your class provides some different methods, since its usually not obvious what would the call do, and explicit is better than implicit in these cases.

Categories

Resources