オーバーライドされた属性アクセスが (期待どおりに) 機能しない

StackOverflow https://stackoverflow.com/questions/1874043

  •  18-09-2019
  •  | 
  •  

質問

次のモジュールの主な目的は、一部の名前に一種の「定数」セマンティクスを提供することです。

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

使用する場合:

>>> 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 そして two は存在しますが、属性へのアクセスは残念です:

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

私が期待しているところ 1 この場合。私のどこが間違っているのでしょうか?

役に立ちましたか?

解決

記述子プロトコルは以下でのみ機能します。 クラスの属性, 、クラスのインスタンスの属性ではありません。を参照してください。 記述子のハウツーガイド

他のヒント

あなたには次のものが欠けています str() または ユニコード定数の () メソッド。

追加:

def __unicode__(self):
    return self._name

私は、彼らが操作できるようにPythonが記述機械へのアクセスからクラスを防ぐことだと思います。それ以外の場合は、ディスクリプタを操作する「魔法」の機能のいくつかの種類せずに非常にトリッキー得ることができる、とあなたはPythonの試行を気づいた場合はアクセス可能言語機械の多くを維持します。これを回避するために、私は多くの場合、その場でクラスを生成しました。たとえば、定数クラスがそうのように宣言することができます:

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

が、本当に、あなたの目的のために、あなたはとのより良いかもしれません。

class Constants(object):
    def __init__(self, content):
       self._content = content
    def __getattr__(self,key):
       return self._content[key]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top