Question

L'objectif principal du module suivant, est de fournir une sorte de sémantique « constante » pour certains noms.

class ConstantError(Exception):

    def __init__(self, msg):
            self._msg = msg


class Constant(object):

    def __init__(self, name):
            self._name = name

    def __get__(self, instance, owner):
            return instance._content[self._name]

    def __set__(self, instance, value):
            raise ConstantError, 'Illegal use of constant'


class Constants(object):

    def __init__(self, content):
            self._content = content
            for k in self._content:
                    setattr(self, k, Constant(k))

num_const = Constants({
    'one': 1,
    'two': 2
})

Quand il est utilisé:

>>> from const import *
>>> dir(num_const)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_content', 'one', 'two']

one et two sont là, mais l'accès d'attribut est diappointing:

>>> num_const.one
<const.Constant object at 0x7faef4871710>
>>> 

Où je Wold attendre 1 dans ce cas. Où suis-je tort?

Était-ce utile?

La solution

Le protocole descripteur ne fonctionne que sur attributs de la classe , et non pas sur les attributs des instances d'une classe. Voir Guide pratique pour Descripteurs

Autres conseils

Il vous manque un str méthode () ou unicode () Constantes.

Ajouter:

def __unicode__(self):
    return self._name

Je pense que python empêche les classes d'accéder à la machinerie de descripteur afin qu'ils puissent être manipulés. Sinon, la manipulation du descripteur pourrait être très difficile sans une sorte de fonction « magique », et si vous avez remarqué essaie de python de garder beaucoup de machines de langage accessible. Pour contourner cela, je l'ai souvent généré la classe à la volée. Par exemple, la classe vous Constantes pourrait être déclarée comme ceci:

class Constants(object):
    def __new__(cls, content):
       class _Constants(object):
           pass
       constants = _Constants
       constants._content = content
       for k in constants._content:
            setattr(_Constants, k, Constant(k))
       return constants

mais vraiment, pour vous besoins que vous pourriez être mieux avec:

class Constants(object):
    def __init__(self, content):
       self._content = content
    def __getattr__(self,key):
       return self._content[key]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top