回答:
プロパティは特別な種類の属性です。基本的に、Pythonが次のコードを検出した場合:
spam = SomeObject()
print(spam.eggs)
それは見上げeggsにspam、次に調べeggs、それが持っているかどうかを確認するために__get__、__set__または__delete__方法を-それがないならば、それは財産です。それならばあるだけ返すのではなく、プロパティeggs(他の属性のために、それは同じように)オブジェクトをそれが呼び出されます__get__メソッド(ルックアップを行っていたため)、そのメソッドが返すものを返します。
プロパティを使用すると、ゲッターメソッド、セッターメソッド、および削除メソッドを完全に制御できます。これらのメソッドには、属性では(警告を使用しない場合は)ありません。
class A(object):
_x = 0
'''A._x is an attribute'''
@property
def x(self):
'''
A.x is a property
This is the getter method
'''
return self._x
@x.setter
def x(self, value):
"""
This is the setter method
where I can check it's not assigned a value < 0
"""
if value < 0:
raise ValueError("Must be >= 0")
self._x = value
>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
File "ex.py", line 15, in <module>
a.x = -1
File "ex.py", line 9, in x
raise ValueError("Must be >= 0")
ValueError: Must be >= 0
x。一方通行。クラスのユーザーが_xについて知った場合は、自己の責任において使用します。
一般的に言えば、プロパティと属性は同じものです。ただし、Pythonには、属性(または他のデータ)へのゲッター/セッターアクセスを提供するプロパティデコレーターがあります。
class MyObject(object):
# This is a normal attribute
foo = 1
@property
def bar(self):
return self.foo
@bar.setter
def bar(self, value):
self.foo = value
obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo
このプロパティを使用すると、通常の属性と同じように値を取得および設定できますが、その下に、メソッドを取得してゲッターとセッターに変換するメソッドがあります。ゲッターとセッターを呼び出すというボイラープレートを減らすのは本当に便利なことです。
たとえば、必要なもののx座標とy座標を保持するクラスがあるとします。それらを設定するには、次のようなことを行います。
myObj.x = 5
myObj.y = 10
それは書くよりも見て、考えるのがはるかに簡単です:
myObj.setX(5)
myObj.setY(10)
問題は、ある日、クラスを変更して、xとyをある値だけオフセットする必要がある場合はどうなるでしょうか。次に、クラス定義とそれを呼び出すすべてのコードを変更する必要がありますが、これには時間がかかり、エラーが発生しやすくなります。このプロパティを使用すると、前者の構文を使用しながら、後者を柔軟に変更できます。
Pythonでは、プロパティ関数を使用して、getter、setter、およびdeleteメソッドを定義できます。readプロパティだけが必要な場合は、メソッドの上に追加できる@propertyデコレータもあります。
サイトから2つの違いを学びました 要約すると、ベルントクラインの。
1.プロパティは、データのカプセル化を行うためのより便利な方法です。
例:パブリック属性の長さのオブジェクトがある場合、後でプロジェクトでカプセル化する必要があります。つまり、プライベートに変更してゲッターとセッターを提供する=>以前に記述したコードの多くを変更する必要があります。
#Old codes
obj1.length=obj1.length+obj2.length
#New codes(Using private attibutes and getter and setter)
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly
@propertyと@ lenght.setter =>を使用する場合、これらの古いコードを変更する必要はありません
2.プロパティは複数の属性をカプセル化できます
class Person:
def __init__(self, name, physic_health, mental_health):
self.name=name
self.__physic_health=physic_health #physic_health is real value in range [0, 5.0]
self.__mental_health=mental_health #mental_health is real value in range [0, 5.0]
@property
def condition(self):
health=self.__physic_health+self.__mental_health
if(health<5.0):
return "I feel bad!"
elif health<8.0:
return "I am ok!"
else:
return "Great!"
この例では、__physic_healthと__mental_healthプライベートであり、アウト側から直接アクセスすることはできません、彼らとの唯一の方法の外のクラスの相互作用はthroughtプロパティですcondition
データのキャッシュまたは更新に使用する明らかな違いも1つあります。多くの場合、クラス属性に接続された関数があります。たとえば、ファイルを1回読み取って、コンテンツを属性に割り当てたままにして、値がキャッシュされるようにする必要があります。
class Misc():
def __init__(self):
self.test = self.test_func()
def test_func(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
出力:
func running
func value
func value
属性に2回アクセスしましたが、関数は1回だけ起動されました。上記の例を変更してプロパティを使用すると、アクセスするたびに属性の値が更新されます。
class Misc():
@property
def test(self):
print 'func running'
return 'func value'
cl = Misc()
print cl.test
print cl.test
出力:
func running
func value
func running
func value