Eredità Python: come disabilitare una funzione
-
04-07-2019 - |
Domanda
In C ++ è possibile disabilitare una funzione nella classe parent dichiarandola come privata nella classe child. Come è possibile farlo in Python? OSSIA Come posso nascondere la funzione del genitore dall'interfaccia pubblica del bambino?
Soluzione
In realtà non ci sono veri " privati ??" attributi o metodi in Python. Una cosa che puoi fare è semplicemente ignorare il metodo che non desideri nella sottoclasse e sollevare un'eccezione:
>>> 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'
Altri suggerimenti
Il metodo di kurosch per risolvere il problema non è del tutto corretto, perché puoi ancora usare b.foo
senza ottenere un AttributeError
. Se non si richiama la funzione, non si verifica alcun errore. Ecco due modi in cui posso pensare di fare questo:
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()
La barra utilizza la "quotazione" " modello per limitare l'accesso all'oggetto avvolto. Martelli ha una buona chiacchierata . Baz utilizza la proprietà integrata per implementare il protocollo descrittore per l'attributo da sovrascrivere.
Una variazione sulla risposta di 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
Ciò genera un AttributeError
sulla proprietà anziché quando viene chiamato il metodo.
L'avrei suggerito in un commento, ma sfortunatamente non ne ho ancora la reputazione.
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
some_function = None
Questo potrebbe portare a delle eccezioni sgradevoli e difficili da trovare, quindi potresti provare questo:
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
def some_function(self):
raise NotImplementedError("function some_function not implemented")
Questo è il modo più pulito che conosco per farlo.
Sostituisci i metodi e chiedi a ciascuno dei metodi sostituiti di chiamare il metodo disabledmethods (). In questo modo:
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()
Potrebbe essere ancora più semplice.
@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