Reputation: 78923
I've read this SO discussion about factory methods, and have an alternate constructor use case.
My class looks like this:
class Foo(object):
def __init__(self, bar):
self.bar = bar
@classmethod
def from_data(cls, datafile):
bar = datafile.read_bar()
# Now I want to process bar in some way
bar = _process_bar(bar)
return cls(bar)
def _process_bar(self, bar)
return bar + 1
My question is, if a @classmethod
factory method wants to use a function in its code, should that function (_proces_bar
) be:
@classmethod
, which seems a bit weird because you won't ever call it like Foo._process_bar()
Foo
but in the same .py
file. I'd go with this, but it seems kind of weird. Will those methods always be available to an instance of Foo
, regardless of how it was instantiated? (e.g. what if it's saved to a Pickle then reloaded? Presumably methods outside the class will then not be available!)@staticmethod
? (see 1. This seems weird)Upvotes: 1
Views: 422
Reputation: 77912
The "right solution" depends on your needs...
If the function (_process_bar
) needs an access to class Foo
(or the current subclass of...) then you want a classmethod
- which should be then called as cls._process_bar()
, not Foo._process_bar()
.
If the function doesn't need an access to the class itself but you still want to be able to override it in subclasses (IOW : you want class-based polymorphism), you want a staticmethod
Else you just want a plain function. Where this function's code lives is irrelevant, and your import problems are othogonal.
Also, you may (or not, depending on your concrete use case) want to allow for more flexiblity using a callback function (possibly with a default), ie:
def process_bar(bar):
return bar + 1
class Foo(object):
@classmethod
def from_data(self, datafile, processor=process_bar):
bar = datafile.read_bar()
bar = processor(bar)
return cls(bar)
Upvotes: 1