Ich möchte in Zusammenhang mit Callisto einen einheitlichen Docstring für die `render()`-Methode eines Renderers schaffen. Das ist so gedacht: Es gibt die Klasse `Renderer`, von der geerbt werden soll. Sie selbst implementiert nur die Doku. Der Code für die Funktion wird von der jeweils abgeleiteten Klasse übernommen. Ziel ist also, den Docstring an die jeweilige `render()`-Methode der abgeleiteten Klasse automatisch anzuheften, sofern noch kein Docstring definiert ist.
Meine Versuche mit `super()` sind bisher kläglich gescheitert. Mir kam noch die Idee einer Metaklasse, aber es ist mir zu umständlich, wenn alle Renderer gezwungen sind, das `__metaclass__`-Attribut zu setzen, was ja - zumindest habe ich das bisher so verstanden - Grundvoraussetzung ist. Bei den Snippets, die man zu dem Thema im Internet findet, weiß ich nicht so recht, ob man sich das echt so kompliziert machen muss. Teilweise wird da mit `__new__` sozusagen als Wrapper u.ä. rumgespielt.
Macht mal bitte Vorschläge, wie ihr es machen würdet.
Docstring vererben
Naja, ich habe schon den `@abstractmethod`-Dekorator angesehen und so. Aber entweder ich schnall es nicht oder es geht nicht. Jedenfalls komme ich nicht dahinter, wie dann ein Attribut (`__doc__` eben) der erbenden Klasse verändert werden kann.
Indem du im __new__ der Metaklasse den Docstring aus den zu entsprechenden Funktionen der Basisklassen in die der Unterklasse kopierst.snafu hat geschrieben:Naja, ich habe schon den `@abstractmethod`-Dekorator angesehen und so. Aber entweder ich schnall es nicht oder es geht nicht. Jedenfalls komme ich nicht dahinter, wie dann ein Attribut (`__doc__` eben) der erbenden Klasse verändert werden kann.
Irgendwie sowas:
Code: Alles auswählen
from abc import abstractmethod, ABCMeta
class CopyDoctring(ABCMeta):
def __new__(self, name, bases, dict):
for base in bases:
for item_name, item in base.__dict__.iteritems():
if getattr(item, "__isabstractmethod__", False):
try:
new_func = dict[item_name]
if not new_func.__doc__:
new_func.__doc__ = item.__doc__
except KeyError: pass
return ABCMeta.__new__(self, name, bases, dict)
class AbstractClass(object):
__metaclass__ = CopyDoctring
@abstractmethod
def get_2(self):
"returns 2"
pass
class Class(AbstractClass):
def get_2():
return 2
print Class.get_2.__doc__
Täusche ich mich, oder ist hier ein Klassendekorator geeigneter und "natürlicher" (Jede Klasse, die diese einleuchtende aber ungewöhnliche Eigenschaft hat ist dann entsprechend "annotiert" in Dekorator Manier)? Man könnte jetzt auch noch den Standard Docstring mittels format() spezialisieren lassen, aber vielleicht ist das Overkill für die angestrebte Verwendung.
Ich frage mich gerade generell, ob man sowas unbedingt braucht. Da es bei "reiner" Vererbung offenbar nicht ohne größere Verrenkungen klappt und ich einen Dekorator dafür übertrieben finde, werde ich mich wohl von der Idee verabschieden.