Devo creare un oggetto che sollevi un'eccezione personalizzata, UnusableObjectError
, quando viene utilizzato in qualsiasi modo (la creazione non dovrebbe tuttavia creare un'eccezione).Oggetto che solleva eccezioni quando utilizzato in qualsiasi modo
a = UnusableClass() # No error
b = UnusableClass() # No error
a == 4 # Raises UnusableObjectError
'x' in a # Raises UnusableObjectError
for i in a: # Raises UnusableObjectError
print(i)
# ..and so on
mi si avvicinò con il codice qui sotto, che sembra comportarsi come previsto.
class UnusableObjectError(Exception):
pass
CLASSES_WITH_MAGIC_METHODS = (str(), object, float(), dict())
# Combines all magic methods I can think of.
MAGIC_METHODS_TO_CHANGE = set()
for i in CLASSES_WITH_MAGIC_METHODS:
MAGIC_METHODS_TO_CHANGE |= set(dir(i))
MAGIC_METHODS_TO_CHANGE.add('__call__')
# __init__ and __new__ must not raise an UnusableObjectError
# otherwise it would raise error even on creation of objects.
MAGIC_METHODS_TO_CHANGE -= {'__class__', '__init__', '__new__'}
def error_func(*args, **kwargs):
"""(nearly) all magic methods will be set to this function."""
raise UnusableObjectError
class UnusableClass(object):
pass
for i in MAGIC_METHODS_TO_CHANGE:
setattr(UnusableClass, i, error_func)
(alcuni miglioramenti apportati, come suggerito da Duncan nei commenti)
Domande:
C'è una classe già esistente che si comporta come descritto?
In caso contrario, c'è qualche difetto nel mio UnusableClass()
(ad esempio, situazioni in cui l'utilizzo delle istanze della classe non genera un errore) e, in caso affermativo, come posso risolvere questi difetti?
impostazione '__' metodi su un'istanza non generalmente funzionare come previsto. Dovresti invece definirli direttamente sulla classe. Ridefinire '__getattribute__' per bloccare l'accesso a qualsiasi attributo diverso da quelli che si desidera consentire sarebbe probabilmente un modo più semplice per fare ciò che si sta tentando. – Duncan
Un esempio che non funzionerà come previsto, prova a chiamare un'istanza: 'a()' restituisce 'TypeError: 'UnusableClass' object is not callable' perché l'impostazione' __call__' sull'istanza viene ignorata. Allo stesso modo 'a [1] = 0'. Naturalmente dal momento che questi non sono implementati faranno comunque un errore, ma non il tuo errore personalizzato. Definire sulla classe potrebbe essere con 'def' o usare semplicemente' setattr' sulla classe piuttosto che sull'istanza. – Duncan
Anche questo sembra un perfetto caso d'uso per i metaclassi ... – thebjorn