python3の日記

Python3を図書とともに勉強していくブログ

【SoloLearn】オブジェクト指向-プロパティ

f:id:pokita:20180527114648p:plain

 

SoloLearn-Object Oriented Programming-Properties

Properties節の第2項の例文コードがよくわからなかったので、今回はそれをまとめます。

以下、よくわからなかったコード。

 

疑問

 

class Pizza:
  def __init__(self, toppings):
  self.toppings = toppings

  @property
  def pineapple_allowed(self):
    return False

  @pineapple_allowed.setter
  def pineapple_allowed(self,value):
    print(value)

pizza = Pizza(["cheese", "tomato"])
print(pizza.pineapple_allowed)
pizza.pineapple_allowed = True

 

この引数valueって何…???

コードの動きを見ていると、pizza.pineapple_allowed = TrueのTrueがvalueに渡されたことがわかる。インスタンスメソッドに代入された値をvalueに渡す…?

しっくりこない。

 

 

改めてPropertiesの本文を読んでみる。

まず@propertyの第1項について。

 

Properties are created by putting the property decorator above a method ,which means when the instance attribute with the same name as the method is accesed,the method will be called instead.

 

propertyはclass内においてはdef表記でfunction(method)として記述されるものの、実際はinstanceのattributteとして、つまりインスタンス変数として扱われる、ということが書いてある。

インスタンス変数はグローバルに属するものなので、クラス外の操作で変更可能だが、@propertyを使えば、変更不可のクラス変数として扱うことができる。

 

動きを見てみる。

@propertyの場合

 

class Pizza:
  def __init__(self, toppings):
  self.toppings = toppings

  @property
  def pineapple_allowed(self):
    return False

 

pizza = Pizza(["cheese", "tomato"])
print(pizza.pineapple_allowed)

>>>False
pizza.pineapple_allowed = True

>>>AttributeError: can't set attribute

#attributeと出ているところが面白い。methodじゃないんかい!

 

クラス変数の場合

 

class Pizza:
  def __init__(self, toppings):
  self.toppings = toppings

  self.pineapple_allowed=False

 

pizza = Pizza(["cheese", "tomato"])
print(pizza.pineapple_allowed)

>>>False
pizza.pineapple_allowed = True

print(pizza.pineapple_allowed) 

>>>True

 

このクラスに属するインスタンスのこの変数は絶対◯◯を返す!

というときに、@propertyは便利そう。

しかし、パイナップルピザってなんなんだろうか。酢豚にパイナップルみたいなもの???

 

次は本丸。@propertyの第2項について。

 

The setter function sets the corresponding property's value.

To define a setter,you need to use a decorator of the same name as the property , followed by a dot and the setter keyword.

 

setter関数は対応するプロパティの値を設定します。

setterを定義するには、プロパティと同名のデコレーターの後に”."と"setter"を付けます。

 

……?????

説明が薄すぎる。

 

プロパティについて検索していると、どうやら答えらしいページにたどり着いた。公式による解説だ。

デスクリプタ HowTo ガイド — Python 3.6.5 ドキュメント

 

……??????

これもこれでよくわかんね。

 

パソコンの大先生たちに聞いてみると、こんな回答を頂いた。

 

class Pizza:
  def __init__(self, toppings):
  self.toppings = toppings

  @property
  def pineapple_allowed(self):
    return False

  @pineapple_allowed.setter
  def pineapple_allowed(self,value):
    print(value)

pizza = Pizza(["cheese", "tomato"])
print(pizza.pineapple_allowed)
pizza.pineapple_allowed = True


におけるpizza.pineapple_allowed= Trueは実質type(pizza(class)).__dict__['pineapple_allowed'(function)].__set__(piza(self), True(value))として処理され 、valueには代入の右辺が直接入るので、インスタンス変数としてのpineapple_allowedは介在できません。

試してみる。

 

class Pizza:
  def __init__(self, toppings):
  self.toppings = toppings

  @property
  def pineapple_allowed(self):
    return False

  @pineapple_allowed.setter
  def pineapple_allowed(self,value):
    print(value)

pizza = Pizza(["cheese", "tomato"])
print(pizza.pineapple_allowed)

>>>False
pizza.pineapple_allowed = True

>>>True

print(pizza.pineapple_allowed)

>>>False

 

ホントだ。最後のprint(pizza.pineapple_allowed)でFalseが出たということは、pizza.pineapple_allowed = Trueでは単にclass内の@pineapple_allowed.setterを起動させ、その引数valueにTrueを渡しただけに過ぎず、インスタンス変数のpizza.pineapple_allowedの値はなんら変わっていないことがわかる。

 

pizza.pineapple_allowed= Trueは実質type(pizza(class)).__dict__['pineapple_allowed'(function)].__set__(piza(self), True(value))として処理され

 

の意味がよくわからない現段階においては、

@properyのsetterはインスタンス変数のpropertyに代入があった際に、class内の@propertyのsetter以下の関数の引数にその値を転送する機能である。

と覚えておくことにする。

 

自作コード

 

単位認定

 

class Subject_Test:
  def __init__(self):
  self.number = "Enter your point"

  @property
  def point(self):
    return self.numner

  @point.setter
  def point(self,value):
    if value > 59:
      print("You succeeded")
    else:
      print("You failed")

 

math = Subject_Test()
print(math.point)

>>>"Enter your point"
math.point=66

>>>"You seucceeded"