42

私のクラスには辞書があります。たとえば、次のようになります。

class MyClass(object):
    def __init__(self):
        self.data = {'a': 'v1', 'b': 'v2'}

次に、辞書のキーを MyClass インスタンスで使用して、辞書にアクセスします。次に例を示します。

ob = MyClass()
v = ob.a   # Here I expect ob.a returns 'v1'

これは __getattr__ で実装する必要があることはわかっていますが、Python は初めてなので、実装方法が正確にはわかりません。

4

8 に答える 8

70
class MyClass(object):

    def __init__(self):
        self.data = {'a': 'v1', 'b': 'v2'}

    def __getattr__(self, attr):
        return self.data[attr]

>>> ob = MyClass()
>>> v = ob.a
>>> v
'v1'

ただし、実装するときは注意してください__setattr__。いくつかの変更を加える必要があります。

class MyClass(object):

    def __init__(self):
        # prevents infinite recursion from self.data = {'a': 'v1', 'b': 'v2'}
        # as now we have __setattr__, which will call __getattr__ when the line
        # self.data[k] tries to access self.data, won't find it in the instance 
        # dictionary and return self.data[k] will in turn call __getattr__
        # for the same reason and so on.... so we manually set data initially
        super(MyClass, self).__setattr__('data', {'a': 'v1', 'b': 'v2'})

    def __setattr__(self, k, v):
        self.data[k] = v

    def __getattr__(self, k):
        # we don't need a special call to super here because getattr is only 
        # called when an attribute is NOT found in the instance's dictionary
        try:
            return self.data[k]
        except KeyError:
            raise AttributeError

>>> ob = MyClass()
>>> ob.c = 1
>>> ob.c
1

属性を設定する必要がない場合は、名前付きタプルを使用してください。

>>> from collections import namedtuple
>>> MyClass = namedtuple("MyClass", ["a", "b"])
>>> ob = MyClass(a=1, b=2)
>>> ob.a
1

デフォルトの引数が必要な場合は、その周りにラッパー クラスを記述できます。

class MyClass(namedtuple("MyClass", ["a", "b"])):

    def __new__(cls, a="v1", b="v2"):
        return super(MyClass, cls).__new__(cls, a, b)

または、関数として見栄えがするかもしれません:

def MyClass(a="v1", b="v2", cls=namedtuple("MyClass", ["a", "b"])):
    return cls(a, b)

>>> ob = MyClass()
>>> ob.a
'v1'
于 2013-04-26T13:28:31.453 に答える
4
class A(object):
  def __init__(self):
     self.data = {'a': 'v1', 'b': 'v2'}
  def __getattr__(self, attr):
     try:
       return self.data[attr]
     except Exception:
       return "not found"


>>>a = A()
>>>print a.a
v1
>>>print a.c
not found
于 2013-04-26T13:35:00.880 に答える
0

この道具の方がかっこいいと思います

class MyClass(object):
    def __init__(self):
        self.data = {'a': 'v1', 'b': 'v2'}
    def __getattr__(self,key):
        return self.data.get(key,None)
于 2016-10-12T08:18:38.170 に答える