I'd like to have a contract on a parameter of some function to enforce the parameter object must have specific property. I understand python isn't a strictly typed language, but having contracts and interfaces is very useful sometimes. Python now has type hints, which is great, so we can do this:
def myfunc(myparam: MyType) -> SomeType:
myparam.myprop # this should exist
But how can I say MyType must have a specific object property (myprop) without inserting assertions and throwing exceptions in run-time? I could define abstract classes with abc metaclasses, which can be used as interfaces.
from abc import ABC, abstractmethod
class MyInterface(ABC):
@property
@abstractmethod
def myprop(self) -> int: pass
now somewhere in the code I could define MyType as:
class MyType(MyInterface):
myprop = 8
It's working, but myprop is a class property and not an object property (attribute). Of course I could do this:
class MyType(MyInterface):
myprop = 0
def __init__(self):
self.myprop = 8
Fine, but I had to define an (unnecessary) class ("static") property and effectively hide it with an object property. Not very clean. Moreover now I have a default value for myprop which is not what I want. But if I do this:
class MyType(MyInterface):
myprop = None # wrong type here
def __init__(self):
self.myprop = 8
it's wrong because, myprop must be int and can not be None, which is correctly caught by the linter. There shall be an object property without a class property.
The goal would be that a static checker like mypy could catch implementation errors where a class doesn't obey the defined interface or contract which requires the parameter instance must have some property.
What is the pythonic (or not so pythonic) way to achieve this?