Domanda

Supponi di avere due classi X & amp; Y. Vuoi decorare quelle classi aggiungendo attributi alla classe per produrre nuove classi X1 e Y1.

Ad esempio:

class X1(X):
  new_attribute = 'something'

class Y1(Y):
  new_attribute = 'something'

new_attribute sarà sempre lo stesso per X1 e Y1. X & amp; Y non sono correlati in alcun modo significativo, tranne per il fatto che l'ereditarietà multipla non è possibile. Esistono anche altri attributi, ma questo è degenerato da illustrare.

Mi sento come se stessi complicando troppo, ma avevo pensato di usare un decoratore, un po 'mi piace:

def _xywrap(cls):
  class _xy(cls):
    new_attribute = 'something'
  return _xy

@_xywrap(X)
class X1():
   pass

@_xywrap(Y)
class Y1():
   pass

Sembra che mi manchi uno schema abbastanza comune e sarei molto obbligato a pensare, a dare input e a feedback.

Grazie per aver letto.

Brian

MODIFICA: Esempio:

Ecco un estratto rilevante che può illuminare. Le classi comuni sono le seguenti:

from google.appengine.ext import db

# I'm including PermittedUserProperty because it may have pertinent side-effects
# (albeit unlikely), which is documented here: [How can you limit access to a
# GAE instance to the current user][1].

class _AccessBase:
   users_permitted = PermittedUserProperty()
   owner = db.ReferenceProperty(User)

class AccessModel(db.Model, _AccessBase):
    pass

class AccessExpando(db.Expando, _AccessBase):
    pass

# the order of _AccessBase/db.* doesn't seem to resolve the issue
class AccessPolyModel(_AccessBase, polymodel.PolyModel):
    pass

Ecco un sotto-documento:

 class Thing(AccessExpando):
     it = db.StringProperty()

A volte Cosa avrà le seguenti proprietà:

 Thing { it: ... }

E altre volte:

 Thing { it: ..., users_permitted:..., owner:... }

Non sono stato in grado di capire perché Thing avrebbe talvolta le sue proprietà _AccessParent, altre volte no.

È stato utile?

Soluzione

Usa 3 argomenti type :

def makeSomeNicelyDecoratedSubclass(someclass):
  return type('MyNiceName', (someclass,), {'new_attribute':'something'})

Questo è davvero, come hai ipotizzato, un linguaggio ragionevolmente popolare.

Modifica : nel caso generale se una sorteggio ha una metaclasse personalizzata, potrebbe essere necessario estrarla e usarla (con un tipo a 1 argomento ) al posto di digita per conservarlo (questo potrebbe essere il caso dei tuoi modelli Django e App Engine):

def makeSomeNicelyDecoratedSubclass(someclass):
  mcl = type(someclass)
  return mcl('MyNiceName', (someclass,), {'new_attribute':'something'})

Funziona anche dove funziona la versione più semplice sopra (poiché in casi semplici senza metaclassi personalizzati type (someclass) è type ).

Altri suggerimenti

Risposta ai tuoi commenti su risposta del viaggiatore :

from google.appengine.ext import db

class Mixin(object):
    """Mix in attributes shared by different types of models."""
    foo = 1
    bar = 2
    baz = 3

class Person(db.Model, Mixin):
    name = db.StringProperty()

class Dinosaur(db.polymodel.PolyModel, Mixin):
    height = db.IntegerProperty()

p = Person(name='Buck Armstrong, Dinosaur Hunter')
d = Dinosaur(height=5000)

print p.name, p.foo, p.bar, p.baz
print d.height, d.foo, d.bar, d.baz

L'esecuzione che risulta in

Buck Armstrong, Dinosaur Hunter 1 2 3
5000 1 2 3

Non è quello che avevi in ??mente?

Perché non puoi usare eredità multipla ?

class Origin:
  new_attribute = 'something'

class X:
  pass

class Y:
  pass

class X1(Origin, X):
  pass

class Y1(Origin, Y):
  pass
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top