Héritage Python - Comment désactiver une fonction
-
04-07-2019 - |
Question
En C ++, vous pouvez désactiver une fonction de la classe parent en la déclarant privée dans la classe enfant. Comment cela peut-il être fait en Python? C'EST À DIRE. Comment masquer la fonction parent de l'interface publique de l'enfant?
La solution
Il n’existe pas vraiment de véritable "privé". attributs ou méthodes en Python. Une chose à faire est simplement de remplacer la méthode que vous ne voulez pas dans la sous-classe et de déclencher une exception:
>>> class Foo( object ):
... def foo( self ):
... print 'FOO!'
...
>>> class Bar( Foo ):
... def foo( self ):
... raise AttributeError( "'Bar' object has no attribute 'foo'" )
...
>>> b = Bar()
>>> b.foo()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 3, in foo
AttributeError: 'Bar' object has no attribute 'foo'
Autres conseils
kurosch pour résoudre le problème n’est pas tout à fait correcte, car vous pouvez toujours utiliser b.foo
sans obtenir un AttributeError
. Si vous n'invoquez pas la fonction, aucune erreur ne se produit. Voici deux façons dont je peux penser à le faire:
import doctest
class Foo(object):
"""
>>> Foo().foo()
foo
"""
def foo(self): print 'foo'
def fu(self): print 'fu'
class Bar(object):
"""
>>> b = Bar()
>>> b.foo()
Traceback (most recent call last):
...
AttributeError
>>> hasattr(b, 'foo')
False
>>> hasattr(b, 'fu')
True
"""
def __init__(self): self._wrapped = Foo()
def __getattr__(self, attr_name):
if attr_name == 'foo': raise AttributeError
return getattr(self._wrapped, attr_name)
class Baz(Foo):
"""
>>> b = Baz()
>>> b.foo() # doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError...
>>> hasattr(b, 'foo')
False
>>> hasattr(b, 'fu')
True
"""
foo = property()
if __name__ == '__main__':
doctest.testmod()
Bar utilise le "wrap". motif pour restreindre l'accès à l'objet encapsulé. Martelli a une bonne conversation à ce sujet. Baz utilise la propriété intégrée pour implémenter le protocole de descripteur pour l'attribut à remplacer.
Une variation de la réponse de kurosch:
class Foo( object ):
def foo( self ):
print 'FOO!'
class Bar( Foo ):
@property
def foo( self ):
raise AttributeError( "'Bar' object has no attribute 'foo'" )
b = Bar()
b.foo
Ceci soulève un AttributeError
sur la propriété au lieu de lorsque la méthode est appelée.
Je l’aurais suggéré dans un commentaire mais n’en ai malheureusement pas encore la réputation.
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
some_function = None
Cela peut toutefois entraîner des exceptions désagréables et difficiles à trouver, vous pouvez donc essayer ceci:
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
def some_function(self):
raise NotImplementedError("function some_function not implemented")
C’est la façon la plus propre que je connaisse de le faire.
Remplacez les méthodes et demandez à chacune d’elles d’appeler votre méthode disabledmethods (). Comme ceci:
class Deck(list):
...
@staticmethod
def disabledmethods():
raise Exception('Function Disabled')
def pop(self): Deck.disabledmethods()
def sort(self): Deck.disabledmethods()
def reverse(self): Deck.disabledmethods()
def __setitem__(self, loc, val): Deck.disabledmethods()
Cela pourrait être encore plus simple.
@property
def private(self):
raise AttributeError
class A:
def __init__(self):
pass
def hello(self):
print("Hello World")
class B(A):
hello = private # that short, really
def hi(self):
A.hello(self)
obj = A()
obj.hello()
obj = B()
obj.hi() # works
obj.hello() # raises AttributeError