Disons que j'ai les deux classes suivantesMéthode accessible uniquement à partir des descendants de classe en python
class A:
def own_method(self):
pass
def descendant_method(self):
pass
class B(A):
pass
et je veux descendant_method
être appelable des instances de B
, mais pas de A
et own_method
pour être appelable de partout .
Je peux penser à plusieurs solutions, tout insatisfaisants:
- Vérifiez un champ et augmenter manuellement
NotImplementedError
:
class A:
def __init__(self):
self.some_field = None
def own_method(self):
pass
def descendant_method(self):
if self.some_field is None:
raise NotImplementedError
class B(A):
def __init__(self):
super(B, self).__init__()
self.some_field = 'B'
pass
Mais cela est en train de modifier le comportement d'exécution de la méthode, que je n » Je veux faire
- Utiliser un mix:
class A:
def own_method(self):
pass
class AA:
def descendant_method(self):
pass
class B(AA, A):
pass
C'est agréable aussi longtemps que descendant_method
n'utilise pas beaucoup de A
, ou bien nous allons devoir hériter AA(A)
et cela défie le point entier
- méthode de marque privée dans
A
et le redéfinir dans une métaclasse:
class A:
def own_method(self):
pass
def __descendant_method(self):
pass
class AMeta(type):
def __new__(mcs, name, parents, dct):
par = parents[0]
desc_method_private_name = '_{}__descendant_method'.format(par.__name__)
if desc_method_private_name in par.__dict__:
dct['descendant_method'] = par.__dict__[desc_method_private_name]
return super(AMeta, mcs).__new__(mcs, name, parents, dct)
class B(A, metaclass=AMeta):
def __init__(self):
super(B, self).__init__()
Cela fonctionne, mais il semble évidemment sale, tout comme l'écriture self.descendant_method = self._A__descendant_method
dans B
lui-même.
Quelle serait la bonne façon "pythonique" d'obtenir ce comportement? UPD: mettre la méthode directement dans B
fonctionnerait, bien sûr, mais je m'attends à ce que A
ait de nombreux descendants qui utiliseront cette méthode et ne voudront pas la définir dans chaque sous-classe.
Si moi-même. \ __ class__ == A? Pas isinstance, test d'égalité? Je l'ai fait pour éviter d'enregistrer des classes "abstraites" lorsque seules les classes concrètes peuvent être utilisées. –
C'est une exigence maladroite d'une méthode, qui indique généralement que vous vous approchez de votre problème. S'il vous plaît expalin * pourquoi * vous voulez faire cela, et quel est le problème original que vous essayez de résoudre en utilisant cette conception. Il pourrait y avoir une meilleure approche. – shx2
@JLPeyret, oui, ce serait mieux que mon numéro 1, mais je veux toujours éviter toute vérification de l'exécution –