Frage

Angenommen, Sie haben zwei Klassen X & Y. Sie wollen, dass diese Klassen dekorieren durch Attribute der Klasse Hinzufügen neuer Klassen X1 und Y1 zu erzeugen.

Zum Beispiel:

class X1(X):
  new_attribute = 'something'

class Y1(Y):
  new_attribute = 'something'

new_attribute wird immer die gleiche sowohl für X1 und Y1. X & Y nicht in sinnvoller Weise im Zusammenhang, mit der Ausnahme, dass die Mehrfachvererbung nicht möglich ist. Es gibt eine Reihe von anderen Attributen als auch, aber das ist degeneriert zu illustrieren.

Ich fühle mich wie ich dies overcomplicating, aber ich hatte gedacht, einen Dekorateur zu verwenden, etwas likeso:

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

@_xywrap(X)
class X1():
   pass

@_xywrap(Y)
class Y1():
   pass

Es fühlt sich an wie ich bin ein ziemlich häufiges Muster fehlt, und ich würde viel für Gedanken, Input und Feedback dazu verpflichtet werden.

Danke für das Lesen.

Brian

EDIT: Beispiel:

Hier ist ein entsprechender Auszug, die beleuchten kann. Die gemeinsamen Klassen sind wie folgt:

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

Hier ist ein Teildokument:

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

Manchmal Sache die folgenden Eigenschaften haben:

 Thing { it: ... }

Und andere Zeiten:

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

Ich habe nicht in der Lage gewesen, um herauszufinden, warum Ding würde manchmal seine _AccessParent Eigenschaften haben, und ein anderes Mal nicht.

War es hilfreich?

Lösung

Mit 3-Argumente geben :

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

Das ist in der Tat, wie Sie vermuten, ein einigermaßen populär Idiom.

Bearbeiten : im allgemeinen Fall, wenn Someclass ein benutzerdefiniertes hat metaclass Sie es (mit einem 1-Argumente type) verwenden extrahieren müssen können anstelle von type selbst, es zu erhalten (dies kann sein, den Fall für Django und App Engine-Modelle):

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

Dies funktioniert auch, wenn die einfachere Version oben tut (da in einfachen Fällen w / ohne individuelle metaclasses type(someclass) is type).

Andere Tipps

Als Reaktion auf Ihre Kommentare zu voyager Antwort :

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

Ausführen, dass die Ergebnisse in

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

Ist das nicht das, was Sie im Sinn hatte?

Warum können Sie nicht verwenden Mehrfachvererbung ?

class Origin:
  new_attribute = 'something'

class X:
  pass

class Y:
  pass

class X1(Origin, X):
  pass

class Y1(Origin, Y):
  pass
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top