Reputation: 898
I have an abstract Python class (v3.8.10) with two abstract methods, save()
and load()
.
import abc
class Parent(abc.ABC):
@abc.abstractmethod
def save(*args, **kwargs):
pass
@abc.abstractmethod
def load(*args, **kwargs):
pass
The purpose of writing such a class is typically to establish an API for downstream development: if you want to inherit from this class, you have to implement save()
and load()
. Now the questions:
Parent
must implement one of these methods (say load()
) as a @classmethod
in order to instantiate the class?save()
) from being implemented as a @classmethod?
These would be additional API constraints required by class Parent
. For example, the following class is instantiable, because it implements save()
and load()
:
class GoodChild(Parent):
def save(self, savefile):
"""Save instance-specific data to a file."""
print(f"saving data to {savefile}")
# ...
@classmethod
def load(cls, loadfile):
"""Load data from a file, creating an instance."""
print(f"loading data from {loadfile}")
# ...
# return cls(data)
But is it possible to write Parent.save()
and Parent.load()
in such a way that the following classes are not instantiable?
class BadChild(Parent):
def save(self, savefile):
print("This is fine.")
def load(self, loadfile):
print("Uh oh, this should be a class method!")
class NaughtyChild(Parent):
@classmethod
def save(cls, savefile):
print("Uh oh, this shouldn't be a class method!")
@classmethod
def load(cls, loadfile):
print("This is fine.")
>>> papa = Parent()
TypeError: #Can't instantiate abstract class Parent with abstract methods load, save
# Can instantiate this class.
>>> child_1 = GoodChild()
# But can also instantiate these. Can we modify Parent so that these raise TypeError?
>>> child_2 = BadChild()
>>> child_3 = NaughtyChild()
Or, if you think such a requirement would be a really bad idea, why?
Upvotes: 2
Views: 705
Reputation: 4368
Yes and no. In Python, many things are possible, but some are very inconvenient.
Why would you want to prevent implementations to use classmethod
? You did not said what load
should do, or of what type are its arguments. And it does not make much sense from the Python data model point of view.
But if you really want, that's what typing
is for in Python : check that something conforms to the expected signature. Even so, having either one of the two methods classmethod
but not the other is quite difficult to express, if not just impossible.
So let me ask you a question : is it really a problem that there are some classmethod
s ? You can't know how the abstract methods will be implemented.
And are staticmethod
s a problem too ?
If so, Python may not be the language to craft such rigid contracts.
Upvotes: 2