Question

Supposons que vous ayez deux classes X & amp; Y. Vous souhaitez décorer ces classes en ajoutant des attributs à la classe pour produire de nouvelles classes X1 et Y1.

Par exemple:

class X1(X):
  new_attribute = 'something'

class Y1(Y):
  new_attribute = 'something'

new_attribute sera toujours le même pour X1 et Y1. X & amp; Y ne sont pas liés de manière significative, sauf que l'héritage multiple n'est pas possible. Il existe également un ensemble d’attributs, mais c’est dégénéré, pour illustrer.

J'ai l'impression de trop compliquer les choses, mais j'avais pensé utiliser un décorateur, un peu comme j'aime:

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

@_xywrap(X)
class X1():
   pass

@_xywrap(Y)
class Y1():
   pass

Il me semble qu’il me manque un schéma assez commun et je serais très obligé de nous faire part de ses réflexions, de sa contribution et de ses commentaires.

Merci d'avoir lu.

Brian

MODIFIER: Exemple:

Voici un extrait pertinent qui peut s’éclairer. Les classes communes sont les suivantes:

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

Voici un sous-document:

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

Parfois, Chose aura les propriétés suivantes:

 Thing { it: ... }

Et d'autres fois:

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

Je ne suis pas parvenu à comprendre pourquoi Thing aurait parfois ses propriétés _AccessParent et d'autres fois.

Était-ce utile?

La solution

Utilisez les 3 arguments tapez :

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

C’est effectivement, comme vous l’imaginez, un idiome relativement populaire.

Modifier : dans le cas général, si une classe a une métaclasse personnalisée, vous devrez peut-être l'extraire et l'utiliser (avec un type à la place de tapez lui-même, pour le conserver (cela peut être le cas pour vos modèles Django et App Engine):

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

Cela fonctionne également à la place de la version simplifiée ci-dessus (car dans les cas simples, aucune métaclasse personnalisée type (someclass) n'est que type ).

Autres conseils

En réponse à vos commentaires sur réponse du voyageur :

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'exécution qui en résulte

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

N’est-ce pas ce que vous aviez en tête?

Pourquoi ne pouvez-vous pas utiliser l'héritage multiple ?

class Origin:
  new_attribute = 'something'

class X:
  pass

class Y:
  pass

class X1(Origin, X):
  pass

class Y1(Origin, Y):
  pass
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top