私のクラスには辞書があります。たとえば、次のようになります。
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 の初心者なので、実装方法が正確にはわかりません。
ベストアンサー1
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
属性を設定する必要がない場合は、namedtuple を使用します。例:
>>> 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'