Dans Scala, je pourrais définir une classe abstraite et la mettre en œuvre avec un objet: mon exemple de béton en python: p> L'héritage n'aurait pas de sens ici, car aucune classe ne pouvait avoir le même trajet J'aimerais avoir: p> Quel serait le moyen de la python 3 de le faire? P> p> code>. Et une seule instance est nécessaire, de sorte que la classe n'agit pas comme un plan pour les objets. Avec d'autres mots: aucune classe n'est nécessaire ici pour un
ressource code> (
book code> dans mon exemple), mais une classe de base est nécessaire pour fournir des fonctionnalités courantes. P>
3 Réponses :
Utilisez un abc code>
(classe de base abstraite) :
import abc class Resource( metaclass=abc.ABCMeta ): @abc.abstractproperty def path( self ): ... return p
Mais que dois-je faire avec un ABC? Un ABC conduirait à la même classe que montré ci-dessus.
@deamon: Oui, mais c'est abstrait i>. Les sous-classes sont nécessaires pour remplacer les propriétés abstraites et les méthodes.
Ce serait mieux qu'une superclasse concrète - je suis d'accord jusqu'à présent. Mais la sous-classe est toujours une classe à partir de laquelle d'autres classes peuvent hériter (le path code>).
@deamon: Oui, c'est correct. Le sous-classement book code> n'est pas une mauvaise idée intrinsèquement - que si vous vouliez un
PaperbackBook code>? Il y a un moyen très élégant de faire cela dans Python, qui est le modèle Borg: code.AcreState.com/recipes/... .
Intéressant Discussion sur le modèle Borg < / a>.
@deamon: Oui, bien qu'il soit également soutenu par le Grand Alex Martelli, il doit donc être quelque chose de bien! Voir la réponse de l'Aaronasterling pour un moyen de prévenir l'héritage, si vous êtes sûr i> que vous voulez faire cela.
Si vous pouvez instancer ressource code> directement, vous le faites simplement et coller le chemin et
obtenez code> méthode directement.
class Object(object):
def __init__(self, name, cls, *args, **kwargs):
self.cls = cls
self.name = name
self.args = args
self.kwargs = kwargs
def __enter__(self):
self.f_locals = copy.copy(sys._getframe(1).f_locals)
def __exit__(self, exc_type, exc_val, exc_tb):
class cls(self.cls):
pass
f_locals = sys._getframe(1).f_locals
new_items = [item for item in f_locals if item not in self.f_locals]
for item in new_items:
setattr(cls, item, f_locals[item])
del f_locals[item] # Keyser Soze the new names from the enclosing namespace
obj = cls(*self.args, **self.kwargs)
f_locals[self.name] = obj # and insert the new object
-1 Cela ne fonctionnera pas, car obtenez code> Voici une fonction au lieu d'une méthode liée (s'appelle-t-on qu'en py3k? Quelque chose comme ça ...). Si vous voulez vraiment faire ce genre de chose, vous devez instancier l'un des types de types
code>. Mais cela ne résout pas le problème, car ce qui est
ressource (). Chemin code> destiné à être?
@katrielaalex Droite. Mon idée originale fonctionne avec des cours. Mes modifications résoutent cependant. book.path code> sera disponible sous forme
self.path code> pour toutes les méthodes d'instance.
@aaron: Maintenant, cela fonctionne, mais ce n'est pas "droit" - les classes de monkeyPatching à ajouter un état crucial n'est pas exactement bonne conception. Se préparer à être assimilé.
De plus, je ne suis pas sûr que c'est une mauvaise conception de MonkyPatch A Book Code> Psuedo-Classe si c'est une partie de la conception i> qu'il n'y a jamais une peine. Il est effectivement considéré comme assez pythonique.
@aaron: heh, mignon! Cela résoudra le problème de l'OP maintenant. Je ne suis pas sûr que j'aime bien l'idée d'empêcher quelqu'un de sous-classement book code> - Et si vous voulez
PaperbackBook code> S? - Mais c'est plus une question de goût que de l'exactitude que je pense.
@KatrielAlex I Personnellement d'accord. Ce n'est pas mon travail de contrôler ce que les gens font avec mes cours, c'est mon travail de ne pas avoir à leur chemin. C'est ce que l'OP veut cependant.
@aaron: vrai que =). Oh, je pense que cela devrait être un typeError, au moins basé sur la manière dont abc code> le fait-il.
Je pense que le concept d'un tel objet n'est pas une manière typique de codage en python, mais si vous devez alors le décorateur Utilisation de ce décorateur Nous obtenons p> class_to_Object code> ci-dessous pour une initialisation immédiate fera le tour. Notez que tous les paramètres d'initialisation de l'objet doivent être passés via le décorateur: p>
>>> @class_to_object(42)
... class K(object):
... def __init__(self, value):
... self.value = value
...
>>> K
<__main__.K object at 0x38f510>
>>> K.value
42
Pourquoi le chemin est-il une variable de classe et non une variable d'instance?
chemin code> est une variable de classe, car le chemin est valide pour la classe entière et non limité à une instance spécifique. Mais comme il n'y a qu'une seule instance, cela n'a pas d'importance de toute façon.
@deamon: En fait, je pense que @ s.lott a un point. Pourquoi ne pouvez-vous pas créer un livre code> générique code>, l'instancez une fois et utilisez cette instance comme livre?
@Katrielaalex: Je pourrais le faire, mais j'aimerais exclure la possibilité que les classes dérivées avaient le même trajet
code>. À cette fin, peu importe qu'il s'agisse d'une classe ou d'une variable d'instance.
@deamon: Oui, ça fait! Si vous instaniez un livre
() code>, vous obtenez un livre
code> avec ce chemin. Si vous créez un
PAPERBACKBOOK (Book) CODE>, il ne recevrait pas automatiquement la variable d'instance i> de votre autre livre
code>.
@katrielaalex ... Mais dans mon scénario concret, l'initialisation serait effectuée dans la méthode
__ init __ code>, de sorte que les sous-classes hériteraient de la variable d'instance lorsqu'ils appellent
super () code>. Mais lorsque je change un peu de conception de l'application, je pourrais aller avec des variables d'instance.