11
votes

Python supporte-t-il quelque chose comme des objets littéraux?

Dans Scala, je pourrais définir une classe abstraite et la mettre en œuvre avec un objet: xxx

mon exemple de béton en python: xxx

L'héritage n'aurait pas de sens ici, car aucune classe ne pouvait avoir le même trajet . 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 ( book dans mon exemple), mais une classe de base est nécessaire pour fournir des fonctionnalités courantes.

J'aimerais avoir: xxx

Quel serait le moyen de la python 3 de le faire?


6 commentaires

Pourquoi le chemin est-il une variable de classe et non une variable d'instance?


chemin 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 générique , 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 . À 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 () , vous obtenez un livre avec ce chemin. Si vous créez un PAPERBACKBOOK (Book) , il ne recevrait pas automatiquement la variable d'instance de votre autre livre .


@katrielaalex ... Mais dans mon scénario concret, l'initialisation serait effectuée dans la méthode __ init __ , de sorte que les sous-classes hériteraient de la variable d'instance lorsqu'ils appellent super () . Mais lorsque je change un peu de conception de l'application, je pourrais aller avec des variables d'instance.


3 Réponses :


2
votes

Utilisez un abc code> (classe de base abstraite) :

import abc
class Resource( metaclass=abc.ABCMeta ):
    @abc.abstractproperty
    def path( self ):
        ...
        return p


6 commentaires

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 . 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 ).


@deamon: Oui, c'est correct. Le sous-classement book n'est pas une mauvaise idée intrinsèquement - que si vous vouliez un PaperbackBook ? 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 que vous voulez faire cela.



1
votes

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      


7 commentaires

-1 Cela ne fonctionnera pas, car obtenez 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 . Mais cela ne résout pas le problème, car ce qui est ressource (). Chemin destiné à être?


@katrielaalex Droite. Mon idée originale fonctionne avec des cours. Mes modifications résoutent cependant. book.path sera disponible sous forme self.path 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 Psuedo-Classe si c'est une partie de la conception 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 - Et si vous voulez PaperbackBook 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 le fait-il.



7
votes

Utilisez un décorateur pour convertir la classe héritée en un objet au moment de la création

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 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> xxx pré>

Utilisation de ce décorateur Nous obtenons p>

>>> @class_to_object(42)
... class K(object):
...     def __init__(self, value):
...         self.value = value
... 
>>> K
<__main__.K object at 0x38f510>
>>> K.value
42


0 commentaires