I have a module, that contains a bunch of functions that generate xml's
In other module I am constructing a class, and I want to assign one of those function to a class variable
Problem is, the fuction acts as a class method and when i call it from another class method, it passes self as a first argument.
Did i choose a good design approach? How to avoid passing self to a function? (@staticmethod decorator before generate = gen.generate doesn't work)
I would like to avoid making a class out of generate function if possible
Thanks!
generators.py
def generate(id, date):
pass
def generate_another():
pass
main.py
import generators as gen
class Client():
generate = gen.generate
def get_result(self, *args, **qwargs):
request = self.generate(id, date)
2 Answers 2
You must understand, that:
@decorator
def some_func():
pass
Is just syntactic sugar for
def some_func():
pass
some_func = decorator(some_func)
So in this case, you just want:
import generators as gen
class Client:
generate = staticmethod(gen.generate)
def get_result(self, *args, **qwargs):
request = self.generate(id, date)
As to whether or not this is a good design decision, it's probably too much of an opion-based question. Personally, I tend to avoid staticmethod
. What advantage does this design offer over simply calling gen.generate
inside get_result
?
1 Comment
This is nearly a duplicate of @juanpa.arrivillaga's answer, but with a simplification which highlights a potential design advantage, addressing Juanpa's question in the case where we're truly using a static method (no self
arg needed).
Code which originally looks like this (class with a decorated static method)...
import generators as gen
class Client:
@staticmethod
def get_result(*args, **qwargs):
request = gen.generate(id, date)
... could be simplified as:
import generators as gen
class Client:
get_result = staticmethod(gen.generate)
In Juanpa's answer, the class has two ways of calling the same underlying gen.generate
:
client = Client()
# 1. as a class method
client.get_result()
# 2. as a static method
client.generate()
This all neglects the details of what is done with the request
object etc, but if the same external function can be recycled completely as a staticmethod in multiple classes, Juanpa's answer helps keep static methods DRY:
def recycled_function(some_arg):
...
class ClassOne:
static_func = staticfunction(recycled_function)
class ClassTwo:
static_func = staticfunction(recycled_function)
This approach is more concise than copying the full implementation of recycled_function
into each class decorated by @staticmethod
, or even by making a wrapper method or static function to call the external recycled_function
.
self.generate
? Why not just call it directly asgen.generate()
. Why should it be a static method instead of a function? This smells strongly of xyproblem.infogenerate
or even an object methodgenerate
that uses state on the object andget_result
would still work. Not saying that's the intent here, but its a reasonable pattern.client = Client(gen.generate)
. Then there's not even a need for the staticmethod decorator