pythonプロパティ管理(1):ベース
8321 ワード
属性を管理するいくつかの方法
pythonでオブジェクトのプロパティにアクセス、設定、削除するには、次の方法があります.組み込み関数getattr()、setattr()およびdelattr() を使用独自に作成する .は、 を決定する. を用いる.ディスクリプタプロトコル を使用 propertyプロトコルを使用します.これは特殊な記述子 です.
本文ではその中の上位4種を簡単に紹介し,後2種を単独の文章で説明する.
組み込み関数XXXXattr()管理プロパティ
組み込み関数getattr()、setattr()、delattr()を使用すると、オブジェクトのプロパティに簡単にアクセス、設定、削除できます.
ヘルプドキュメントを参照してください.
操作するオブジェクトobjと操作する属性名nameを指定するのは簡単です.getattr()の場合、操作する属性が存在しない場合はデフォルトでエラーが報告されます.defaultパラメータが属性が存在しないことを示すときに、その属性値を返すことができます.
たとえば、以下は簡単なPersonクラスとオブジェクトpです.
getattr()を使用して、nameプロパティと存在しないageプロパティを取得します.
上からage属性にアクセスすると、3番目のパラメータ「23」を削除すると異常が放出されます.
setattr()とdelattr()を使用して、プロパティを設定および削除します.
結果を返します.
自己作成アクセスメソッド
一般的にオブジェクト向けの言語は、自分でsetter、getter、deleterメソッドを書いて属性を管理するもので、汎用的で安全ですが、管理するのはそんなに便利ではありません.
ここでは、pythonがオブジェクトのプロパティを設定することを参照してください.
たとえば、Personクラスにname、ageの2つのプロパティのaccessorメソッドを追加します.
欠点は明らかで、管理したい各属性に対して、これらの属性を定義しなければならない.すなわち,accessorメソッドは単一の属性に対するものである.
演算子リロード管理属性
通常、ポイント演算を直接使用してプロパティにアクセスしたり、設定したりすることができます.例:
まず,オブジェクトの付与と削除操作,すなわち上の(2)と(3)である.この2つの操作は、
さらに、属性にアクセスする操作(1)について、pythonは、2つの対応する方法
ここでは、後で発生する問題のまとめを先に説明します.すべての属性操作に適用される
__getattr__()
例:
上記のPersonクラスには属性nameがあるため、name属性にアクセスすると
出力結果は次のとおりです.
__getattribute__()
この方法の
解決策は、super()やobjectクラスなどの親クラスからアクセスすることです.
例:
結果を返します.
nameとageの2つの属性が出力されたが、「p.age」が出力されるとその属性は存在せず、
無限再帰問題を解決する上で、後の
__setattr__()
呼び出し
唯一注意しなければならないのは、付与時の無限再帰問題を避けることです.
したがって、
以下の例を参照してください.
実行結果:
問題が発見された可能性があります.
__delattr__()
同様に注意すべきは,付与時の無限再帰問題を回避することである.
例:
pythonでオブジェクトのプロパティにアクセス、設定、削除するには、次の方法があります.
getter()
、setter()
、deleter()
の方法__getattr__()
、__setattr__()
、__delattr__()
の演算子をリロードし、x.y
のアクセス、付与方式、およびdel x.y
の方式__getattribute__()
法本文ではその中の上位4種を簡単に紹介し,後2種を単独の文章で説明する.
組み込み関数XXXXattr()管理プロパティ
組み込み関数getattr()、setattr()、delattr()を使用すると、オブジェクトのプロパティに簡単にアクセス、設定、削除できます.
ヘルプドキュメントを参照してください.
getattr(...)
getattr(object, name[, default]) -> value
Get a named attribute from an object;
getattr(x, 'y') is equivalent to x.y.
setattr(obj, name, value, /)
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
delattr(obj, name, /)
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
操作するオブジェクトobjと操作する属性名nameを指定するのは簡単です.getattr()の場合、操作する属性が存在しない場合はデフォルトでエラーが報告されます.defaultパラメータが属性が存在しないことを示すときに、その属性値を返すことができます.
たとえば、以下は簡単なPersonクラスとオブジェクトpです.
class Person():
def __init__(self, name):
self.name = name
p = Person("malongshuai")
getattr()を使用して、nameプロパティと存在しないageプロパティを取得します.
print(getattr(p, "name"))
print(getattr(p, "age", 23))
上からage属性にアクセスすると、3番目のパラメータ「23」を削除すると異常が放出されます.
AttributeError: 'Person' object has no attribute 'age'
setattr()とdelattr()を使用して、プロパティを設定および削除します.
setattr(p, "age", 25)
print(p.__dict__)
delattr(p, "age")
print(p.__dict__)
結果を返します.
{'name': 'malongshuai', 'age': 25}
{'name': 'malongshuai'}
自己作成アクセスメソッド
一般的にオブジェクト向けの言語は、自分でsetter、getter、deleterメソッドを書いて属性を管理するもので、汎用的で安全ですが、管理するのはそんなに便利ではありません.
ここでは、pythonがオブジェクトのプロパティを設定することを参照してください.
たとえば、Personクラスにname、ageの2つのプロパティのaccessorメソッドを追加します.
class Person():
def __init__(self, name):
self.name = name
def set_name(self,name): self.name = name
def get_name(self): return self.name
def del_name(self): del self.name
def set_age(self,age): self.age = age
def get_age(self): return self.age
def del_age(self): del self.age
欠点は明らかで、管理したい各属性に対して、これらの属性を定義しなければならない.すなわち,accessorメソッドは単一の属性に対するものである.
演算子リロード管理属性
通常、ポイント演算を直接使用してプロパティにアクセスしたり、設定したりすることができます.例:
p.name # (1) p name
p.name = "abc" # (2) p name
del p.name # (3) p name
まず,オブジェクトの付与と削除操作,すなわち上の(2)と(3)である.この2つの操作は、
__setattr__()
、__delattr__()
の2つの方法によって直接ブロックされるか、あるいは、この2つの方法が書き換えられさえすれば、属性に値を付与し、削除するたびに、対応する2つの方法が呼び出される.さらに、属性にアクセスする操作(1)について、pythonは、2つの対応する方法
__getattr__()
および__getattribute__()
を提供する.前者は存在しない属性にアクセスするときに自動的に呼び出され、後者は属性にアクセスするときに呼び出され、属性が存在するかどうかを無視します.ここでは、後で発生する問題のまとめを先に説明します.すべての属性操作に適用される
__setattr__
、__delattr__
、__getattribute__
の方法では、それらの無限の再帰を避ける必要があります.以下の例を参照すれば分かる.__getattr__()
__getattr__()
は、存在しない属性にドットアクセスすることによって呼び出される.プロパティ値を返すか、例外を放出するかの2つの使用基準があります.例:
class Person():
def __init__(self, name):
self.name = name
def __getattr__(self, attrname):
if attrname == "name":
print("in getattr1")
return self.name
elif attrname == "age":
print("in getattr2")
return 25
else:
print("in getattr3")
raise AttributeError(attrname)
p = Person("malongshuai")
上記のPersonクラスには属性nameがあるため、name属性にアクセスすると
__getattr__()
は呼び出されず、ageまたは他の属性にアクセスするとメソッドが呼び出されますが、age属性にはカスタムの戻り値があり、他の属性はエラーを報告します.print(p.name)
print(p.age)
print(p.job)
出力結果は次のとおりです.
malongshuai
in getattr2
25
in getattr3
Traceback (most recent call last):
File "g:/pycode/b.py", line 21, in
print(p.job)
File "g:/pycode/b.py", line 14, in __getattr__
raise AttributeError(attrname)
AttributeError: job
__getattribute__()
__getattribute__()
と__getattr__()
は同様であり、ターゲット属性が存在するかどうかにかかわらず、前者はすべての属性へのアクセスに適している.__getattribute__()
は、すべての属性アクセス操作に適用されるため、無限の再帰を避ける必要があることに注意してください.たとえば、次は間違った書き方です.def __getattribute__(self, attr):
return self.attr
この方法の
self.attr
は、__getattribute__
の呼び出しをトリガし続け、無限再帰問題が発生するからである.解決策は、super()やobjectクラスなどの親クラスからアクセスすることです.
super().__getattribute__(attr)
object.__getattribute__(self, attr)
__getattribute__()
の優先度は__getattr__()
より高く、前者が存在する場合、前者のコードで後者が呼び出されていないか、前者が異常を投げ出さない限り、後者は呼び出されません.例:
class Person():
def __init__(self, name):
self.name = name
def __getattribute__(self, attr):
print("in getattribute")
return object.__getattribute__(self, attr)
# return super.__getattribute__(attr)
def __getattr__(self, attrname):
if attrname == "name":
print("in getattr1")
return self.name
elif attrname == "age":
print("in getattr2")
return 25
else:
print("in getattr3")
raise AttributeError(attrname)
p = Person("malongshuai")
print(p.name)
print(p.age)
結果を返します.
in getattribute
malongshuai
in getattribute
in getattr2
25
nameとageの2つの属性が出力されたが、「p.age」が出力されるとその属性は存在せず、
__getattribute__
が異常を放出し、__getattr__
がトリガーされる.無限再帰問題を解決する上で、後の
__setattr__
および__delattr__
には、__dict__
にアクセスする方法もある.これは、この辞書へのアクセスが__getattribute__
をトリガし、無限再帰を継続するため、ここの__getattribute__
には適していない.__setattr__()
__setattr__()
は、オブジェクト属性付与動作をブロックするために使用される.例:p.name = "long"
呼び出し
p.__setattr__(self,name,"long")
に変換されます.唯一注意しなければならないのは、付与時の無限再帰問題を避けることです.
__setattr__()
における付与文self.attr = value
は、このメソッドを呼び出し続け、最終的には無限再帰をもたらすからである.したがって、
__setattr__()
メソッドでは、__dict__
を使用して属性を取得し、付与するか、親の同名属性にアクセスする必要があります.したがって、無限再帰呼び出しを回避するには、次のいくつかの方法があります.self.__dict__[attr] = value
super().__setattr__(attr, value)
object.__setattr__(self, attr, value)
以下の例を参照してください.
class Person():
def __init__(self, name):
self.name = name
def __setattr__(self, attr, value):
print("in setattr")
#self.__dict__[attr] = value
#super().__setattr__(attr, value)
object.__setattr__(self, attr, value)
p = Person("malongshuai")
p.age = 33 # __setattr__()
print(p.age)
実行結果:
in setattr
in setattr
33
問題が発見された可能性があります.
in setter
の値付け操作も__init__()
をトリガーするため、__setattr__()
が2回出力されます.__delattr__()
del x.y
が呼び出されると、__delattr__()
の呼び出しが自動的にトリガーされます.同様に注意すべきは,付与時の無限再帰問題を回避することである.
__delattr__()
のdel文は、メソッドを呼び出し続ける可能性があるため、最終的には無限再帰をもたらす可能性があります.したがって、__delattr__()
メソッドでは、__dict__
を使用して属性を取得し、付与するか、親の同名属性にアクセスする必要があります.したがって、無限再帰呼び出しを回避するには、次のいくつかの方法があります.del self.__dict__[attr]
super().__delattr__(attr)
object.__delattr__(self, attr)
例:
class Person():
def __init__(self, name):
self.name = name
def __delattr__(self, attr):
print("%s deleting" % (attr))
#del self.__dict__[attr]
#super().__delattr__(attr)
object.__delattr__(self, attr)
print("%s deleted" % (attr))
p = Person("malongshuai")
p.age = 33
del p.age