I need to extend a classmethod in Python in multiple files.
Let's say, for the sake of decades of tradition, that we have a class Animal
which has a method called Animal.eat
And let's imagine we have a bunch of different modules, eat
, swallow
and taste
# chew/__init__.py
import Animal
def eat():
print('chewing')
super(Animal, self).eat()
Animal.eat = eat <------------ This does not work
# swallow/__init__.py
import Animal
def eat():
print('swallowing')
super(Animal, self).eat()
Animal.eat = eat <------------ This does not work
# taste/__init__.py
import Animal
def eat():
print('tasting')
super(Animal, self).eat()
Animal.eat = eat <------------ This does not work
And then we have our main.py
import Animal
import chew
import swallow
import taste
animal = Animal()
animal.eat()
Calling animal.eat()
should print out
chewing
swallowing
tasting
But the only thing that happens is that it prints out tasting
Can it be done?
There are different to go about this, personally I would use some sort of register
classmethod to add to the Animal
class from wherever.
class Animal(object):
_EAT_ACTIONS = []
def eat(self):
for action in self._EAT_ACTIONS:
action()
@classmethod
def register_eat_action(cls, action):
cls._EAT_ACTIONS.append(action)
def chew():
print('chewing')
Animal.register_eat_action(chew)
def swallow():
print('swallowing')
Animal.register_eat_action(swallow)
def taste():
print('tasting')
Animal.register_eat_action(taste)
Animal().eat()
# chewing
# swallowing
# tasting
With the way you were attempting to do in the question, the working version would be somewhat like this, but I'd suggest not do it as it's quite messy.
eat = Animal.eat
def chew(self):
print('chewing')
return eat(self)
Animal.eat = chew
Edit: Alternative idea with inheritance:
class Animal(object):
Chews = False
def eat(self):
if self.Chews:
print('chewing')
class Dog(Animal):
Chews = True
To extend Animal
you need to define a new class which inherits from Animal
... it seems like you want to define a base animal class and a bunch of mixins.
You can do this like:
from abc import ABC, abstractmethod
class BaseAnimal(ABC):
@abstractmethod
def eat(self):
return NotImplemented
class Chews:
def eat(self):
print('chewing')
super().eat()
class Swallows:
def eat(self):
print('swallowing')
super().eat()
class Tastes:
def eat(self):
print('tasting')
super().eat()
class Animal(Chews, Swallows, Tastes, BaseAnimal):
pass
and it gives:
In [14]: Animal().eat()
chewing
swallowing
tasting
To be honest this is a bad use for mixins though, they should provide independent new functionality (eg chew()
, swallow()
, taste()
methods) instead of extending existing functionality
So on balance I prefer @Peter's answer for your use case.
But I wanted to demonstrate how to do the kind of inheritance you appeared to be trying to do.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.