host_name、kernel_version、bios_versionなどのコンピュータに関する詳細を取得するためのクラスを作成しています。いくつかの詳細は他のものよりも高価ですので、私はそれらを取得するget_ *関数を持っていますが、それらが再び必要になった場合にはオブジェクトにキャッシュされた結果を保持します。私は、カーネルのバージョンはように取得することができるので、辞書オブジェクトのように見えるようにそれらを実装検討しています:固定の読み取り専用フィールドの動的属性またはカスタム辞書
system = System()
kver = system['kernel_version']
これは、データを取得するために内部的にインスタンスメソッドget_kernel_version(self)
を呼び出します。上記のインスタンス化されたオブジェクトから2回目にカーネルのバージョンが取得された場合、元の呼び出しのキャッシュ結果がget_kernel_version(self)
に返されます。これらのキーと値のペアはすべて読み取り専用であり、利用可能なget_ *メソッドに基づいて固定数があり、後で追加することはできないため、通常の辞書のようには感じられません。 values()
のような関数を呼び出す必要はありません。この関数は、すべてのget_ *関数が不必要にヒットすることになります。また、構文は私が望むよりも少し冗長です。代わりにsystem.kernel_version
を使用すると、この使用例の方が自然なようです。
クラスインスタンスで動的属性を使用する方がよいかどうか検討しています。しかし、すべての属性のリストを取得するための自然な方法が必要ですが、それらをサポートする内部メソッドは必要ありません。おそらく__dir__
特別な方法を使用して、keys()
の辞書リストに似たリストを返します。カーネルバージョンとホスト名がリストに表示されますが、__class__
またはget_kernel_version
は表示されません。これは、__dir__
の定義のための推奨された習慣に反するように思われるので、これが正しいアプローチであるかどうかはわかりません。
適切な属性が既に定義されていない場合、get_ *関数を使用して具体的なクラスにコールバックするプロキシクラスインスタンスを返すことができます。ここで
私は辞書のアプローチを実装して実験していたバージョンの例です:
次の出力を生成class System(dict):
def __getitem__(self, key):
try:
return getattr(self, 'get_'+key)()
except AttributeError as ex:
raise KeyError(ex.message)
def __setitem__(self, key, value):
raise Exception('Read-only')
def __delitem__(self, key, value):
raise Exception('Read-only')
def keys(self):
return [ x[4:] for x in dir(self) if x.startswith('get_') ]
def get_host_name(self):
return 'localhost'
def get_kernel_version(self):
return '4.7.0'
system = System()
print repr(system.keys())
for key in system.keys():
print '{0}: {1}'.format(key, system[key])
try:
system['bios']
except Exception as ex:
print str(ex)
try:
system['kernel_version'] = '5.0'
except Exception as ex:
print str(ex)
:
['host_name', 'kernel_version']
host_name: localhost
kernel_version: 4.7.0
"'System' object has no attribute 'get_bios'"
Read-only
上記のコードはまだキャッシュを実装していません。値はまだありませんが、追加するのは簡単です。しかし、私は属性としてこれを行うべきであるように感じています。私はそれを行うときに私がkeys()
と同じ機能をエミュレートするために__dir__
を乱用すべきかどうかだけはわかりません。
私は、読み取り専用辞書をエミュレートするか、動的属性を持つクラスインスタンスを提示する必要がありますか?
あなたができるようになる。このような何か[ 'AttrDict'レシピ](https://code.activestate.com/recipes/576972-attrdict/)を使用することができます(__getattr __()を使って内容へのアクセスを制御する方法もあります)どちらの方法でもキャッシュをサポートすることができます[あなたの質問を編集し、特にいくつかのサンプルコードを追加することでより具体的にすると、おそらく追加の詳細を提供することができます。 – martineau
@martineau私がlookiって何の基本的な考え方の例を追加しました〜のために。 – penguin359
あなたのコードを見て、もう少し考えてみたら、あなたが持っているものは基本的にOKだと思います。あなたが持っている 'keys()'メソッドのデータを自動的に生成するように拡張することができます。下記の[私の答え](http://stackoverflow.com/a/39171820/355230)を参照してください。 – martineau