Domanda

Sto usando la tipizzazione anatra in Python.

def flagItem(object_to_flag, account_flagging, flag_type, is_flagged):
    if flag_type == Flags.OFFENSIVE:
        object_to_flag.is_offensive=is_flagged
    elif flag_type == Flags.SPAM:
        object_to_flag.is_spam=is_flagged
    object_to_flag.is_active=(not is_flagged)
    object_to_flag.cleanup()
    return object_to_flag.put()

Dove sono passati come object_to_flag oggetti diversi, che hanno tutti gli attributi is_active, is_spam, is_offensive. Accadono anche avere un metodo cleanup().

Gli oggetti che sto passando tutti hanno la stessa classe di base (sono oggetti db in Google App Engine):

class User(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

class Post(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

Come posso fare il metodo cleanup() così astratto che io possa avere la stessa classe genitore per tutti questi oggetti che richiede i bambini forniscono implementazione?

Forse ancora più importante, è questo 'divinatorio'? Dovrei seguire questa strada, o devo solo fare affidamento sulla tipizzazione anatra? Il mio background è in Java e sto cercando di imparare il modo Python di fare le cose.

Grazie!

È stato utile?

Soluzione

Dal momento che non si dispone di abc disponibili, è possibile farlo con un semplice metaclasse

class Abstract(type(db.Model)):
    def __new__(metacls, clsname, bases, clsdict):
        for methodname in clsdict.pop('_abstract_methods_', []):
            try:
                if not callable(clsdict[methodname]):
                    raise TypeError("{0} must implement {1}".format(clcname, methodname))
            except KeyError:
                raise TypeError("{0} must implement {1}".format(clcname, methodname))
       return super(Abstract, metacls).__new__(metacls, clsname, bases, clsdict)


class RequireCleanup(db.Model):
    __metaclass__ = Abstract
    _abstract_methods_ = ['cleanup']

    def cleanup(self):
        pass

si risolve espressione type(db.Model) a qualunque metaclasse si abitua per db.Model quindi non lo facciamo passo sul codice di Google. Inoltre, abbiamo pop _abstract_methods_ fuori del dizionario di classe prima di venire di passare a Google di metodo __new__ in modo che noi non rompere nulla. Se db.Model ha già un attributo con quel nome, allora si avrà bisogno di cambiare a qualcosa d'altro.

Altri suggerimenti

Utilizzare la abc modulo . In particolare, impostare metaclasse del vostro classe base per ABCMeta e utilizzare il decoratore @abstractmethod sul metodo di cleanup.

Il dibattito sulla questione se questo è "divinatorio" è diviso. PEP 3119 , che descrive lo standard, elenca alcuni dei pro e dei contro ( ma ovviamente favorisce ABC). Ha reso nella libreria standard, che è una bella indicazione bene che molte persone ritengono utile in alcune circostanze. Nel tuo caso, penso che sia appropriata.

Se si vuole garantire che il metodo di pulitura è implementato, si può avvolgere con il decoratore @abc.virtualmethod. Questo causerà un errore in istanza di qualsiasi oggetto che non ha sovrascritto le virtualmethod. Questo richiede anche che si fanno abc.ABCMeta __metaclass__ della vostra classe.

abc modulo per maggiori informazioni e alcuni esempi.

Questa non è comunemente fatto: di solito ci sarà solo documenti secondo i quali gli implementatori devono eseguire l'override il metodo indicato. Tuttavia, questo può essere più a causa della novità del modulo abc (nuovo in Python 2.6) di un unpythonicness percepita di questo approccio.

Perché non hanno il metodo cleanup solo sollevare un NotImplementedError quando viene chiamato? Se vogliono le vostre classi figli a lavorare avranno a mettere una sorta di implementazione in atto.

Anche se non ho mai usato personalmente, ho visto molti riferimenti a interfacce Zope . Questo può essere eccessivo per il vostro compito, ma può dare qualche direzione. E può stare tranquillo a qualcuno con un background di Java.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top