__getattr__
私はビルトインに出くわし、いつ使用されるのだろうと思っていました。
ドキュメントhttp://docs.python.org/reference/datamodel.html#から実用的な使い方を考えるのに苦労しました。それがコードでどのように使用され、役立つかを示す実際の例は何ですか?
4 に答える
1 つの例は、辞書でオブジェクト表記を使用することです。たとえば、辞書を考えてみましょう
myDict = {'value': 1}
通常、Python では、「値」変数に次のようにアクセスします。
myDict['value']
これは1
Python インタープリターで出力されます。ただし、myDict.value
表記法を使用したい場合があります。これは、次のクラスを使用して実現できます。
class DictAsMember(dict):
def __getattr__(self, name):
value = self[name]
if isinstance(value, dict):
value = DictAsMember(value)
return value
my_dict = DictAsMember()
my_dict['property'] = {'sub_property': 1}
print(my_dict.property.sub_property) # 1 will be printed
__getattr__
は属性が見つからない場合にのみ呼び出されるため、属性を検索する代替の場所を定義したり、 のようにデフォルト値を指定したりするのに便利な方法ですdefaultdict
。
ここでのすべての検索を別のオブジェクトに委譲することによって、オブジェクトの MRO 内の他のすべてより上位の基本クラスをエミュレートすることもできます (ただし、これを行うと、他のオブジェクトが属性を委譲している場合、無限ループが発生する可能性があります)。
もあり__getattribute__
、これは、オブジェクトで属性が検索されるたびに呼び出されるという点で関連しています。
使用例は、いくつかのオブジェクトの周りに単純なラッパーを作成することです。たとえば、呼び出しをログに記録したり、継承せずに動作を変更したり、オブジェクトのインターフェイス全体を実装したりする必要がありません。
たとえばhttp://western-skies.blogspot.fr/2008/02/complete-example-of-getattr-in-python.htmlのように、文書化された優れた例がいくつかあります。
編集:これはメソッドgetattr
ではなく組み込み関数に関するものです。__getattr__
ベアラー トークンを使用する REST クライアントに対してこれを行う必要がありました。Requestsの Session オブジェクトを独自のインターフェイスにラップして、常に auth ヘッダーを送信し、(より適切に) URL のパスを使用して同じサイトに HTTP リクエストを送信できるようにしました。
class RequestsWrapper():
def __init__(self, base_url):
self.client = requests.Session(
headers={'Authorization':'myauthtoken'}
)
self.base_url = base_url
def _make_path_request(self, http_method, path, **kwargs):
"""
Use the http_method string to find the requests.Session instance's
method.
"""
method_to_call = getattr(self.client, http_method.lower())
return method_to_call(self.base_url + path, **kwargs)
def path_get(self, path, **kwargs):
"""
Sends a GET request to base_url + path.
"""
return self._make_path_request('get', path, **kwargs)
def path_post(self, path, **kwargs):
"""
Sends a POST request to base_url + path.
"""
return self._make_path_request('post', path, **kwargs)
def path_put(self, path, **kwargs):
"""
Sends a PUT request to base_url + path.
"""
return self._make_path_request('put', path, **kwargs)
def path_delete(self, path, **kwargs):
"""
Sends a DELETE request to base_url + path.
"""
return self._make_path_request('delete', path, **kwargs)
次に、パスに基づいてリクエストを作成できます。
# Initialize
myclient = RequestsWrapper("http://www.example.com")
# Make a get request to http://www.example.com/api/spam/eggs
response = myclient.path_get("/api/spam/eggs")
# Print the response JSON data
if response.ok:
print response.json