import abc from typing import ClassVar from pydantic import BaseModel from devtools import debug class Fruit(BaseModel, abc.ABC): @property @abc.abstractmethod def type(self) -> str: """The name of the type of fruit.""" class Apple(Fruit): type: ClassVar[str] = "apple" size: int a = Apple(size=4) debug(a, a.type)
Unless you want to allow type to be changed when creating a model instance, in which case just make it a field on Fruit.
[abc] Add abstract attributes via `abstract` type-hint - Ideas - Discussions on Python.org
How to create abstract properties in python abstract classes? - Stack Overflow
Enforcing Abstract Property in Python Classes - TestMu AI Community
Access abstract class property from class method
What is an abstract class in Python?
Can an abstract class have properties in Python?
Can we instantiate an abstract class in Python?
Videos
Since Python 3.3 a bug was fixed meaning the property() decorator is now correctly identified as abstract when applied to an abstract method.
Note: Order matters, you have to use @property above @abstractmethod
Python 3.3+: (python docs):
from abc import ABC, abstractmethod
class C(ABC):
@property
@abstractmethod
def my_abstract_property(self):
...
Python 2: (python docs)
from abc import ABCMeta, abstractproperty
class C:
__metaclass__ = ABCMeta
@abstractproperty
def my_abstract_property(self):
...
Until Python 3.3, you cannot nest @abstractmethod and @property.
Use @abstractproperty to create abstract properties (docs).
from abc import ABCMeta, abstractmethod, abstractproperty
class Base(object):
# ...
@abstractproperty
def name(self):
pass
The code now raises the correct exception:
Traceback (most recent call last):
File "foo.py", line 36, in
b1 = Base_1('abc')
TypeError: Can't instantiate abstract class Base_1 with abstract methods name
I come from a C++ background, and I need to write an abstract base class, that inherits from abc. In this abstract base class, I would like to "declare" (this is C++ lingo, but I don't think variable declaration is a thing in Python) an uninstantiated variable, say `var`, which is initialized in the subclasses.
I'm wondering if there's any way to do this in Python?
After some thought, I think the second code snippet does not use the Factory method as it is not concerned with the creation of objects.
However, the code can be refactored to use the Factory method and better communicate the intent:
class CraneInterface(ABC):
def __init__(self):
self.__axis = self._make_axis()
@property
def axis(self) -> AxisInterface:
return self.__axis
@abstractmethod
def _make_axis(self) -> AxisInterface:
"""
Factory method: "Subclasses override to change the class of object that will be created"
"""
pass
To re-iterate the most important part of your quote from Refactoring Guru:
Factory Method defines a method, which should be used for creating objects instead of direct constructor call.
If the function that returns an AxisInterface does not have the purpose of creating an axis for the caller, then you are not using the Factory Method pattern, regardless of how much your code resembles the implementation of the pattern.
Design patterns are not defined by their structure but by the intent of the code.