Domanda

L'obiettivo principale del modulo successivo, è quello di fornire una sorta di semantica "costante" per alcuni nomi.

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

Quando viene utilizzato:

>>> 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']

Così one e two ci sono, ma l'accesso agli attributi è diappointing:

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

Dove ho wold aspettare 1 in questo caso. Dove mi sbaglio?

È stato utile?

Soluzione

Il protocollo descrittore funziona solo su attributi della classe , non sugli attributi di istanze di una classe. Vedere la Guida alle procedure per descrittori

Altri suggerimenti

Ti manca un str () o unicode () metodo Costanti.

Add:

def __unicode__(self):
    return self._name

Credo Python impedisce classi di accedere alla macchina descrittore in modo che possano essere manipolati. In caso contrario, manipolando il descrittore potrebbe diventare molto difficile senza un qualche tipo di funzione 'magico', e se avete notato cerca pitone per mantenere un sacco di macchine linguaggio accessibile. Per ovviare a questo ho spesso generato la classe al volo. Ad esempio, classe che si Costanti potrebbe essere dichiarato in questo modo:

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

, ma in realtà, per voi scopi potrebbe essere meglio di con:

class Constants(object):
    def __init__(self, content):
       self._content = content
    def __getattr__(self,key):
       return self._content[key]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top