2016-06-22 21 views
0

以下のコードを定義したダッククラスビルクラスおよびテールクラス。私の質問は、方法についてはについて()の内部ダッククラス定義は、なぜbill.descriptiontail.lengthを書くことができますか? selfはここでは省略されていますか?はいの場合は、いつselfを省略できますか? __init__の方法で省略することはできますか?次のようにPythonでは、selfを省略できますか?

class Bill(): 
    def __init__(self, description): 
     self.description = description 
class Tail(): 
    def __init__(self, length): 
     self.length = length 
class Duck(): 
    def __init__(self, bill, tail): 
     self.bill = bill 
     self.tail = tail 
    def about(self): 
     print('This duck has a', bill.description, 'bill and a', tail.length, 'tail') 
tail = Tail('long') 
bill = Bill('wide orange') 
duck = Duck(bill, tail) 
duck.about() 

出力はあなたがここで参照されているグローバル変数billtailを、定義されているので、ことを書くことができ、 enter image description here

+5

実際にはグローバルスコープから 'tail'と' bill'という名前を使用します。作成を 'tail1 = Tail( 'long')'に変更してみてください。 - NameErrorが発生します。 –

+0

なぜあなたは自己を省略したいですか?そのオブジェクトを参照するためにオブジェクトで使用されるPython言語固有の構造体。あなたがそれを使わないなら、あなたはグローバルな文脈を参照しています。 –

+0

@WaxCage about()メソッドでself.bill.descriptionとself.tail.lengthを書けば、私のコードもうまくいくことを知っているからです。しかし、私は自己を省略することもできることに驚きました! – Nicholas

答えて

4

は長い話を短くするには:あなたがの属性(データ属性、プロパティまたはメソッド)にアクセスしたいときMUST使用self.現在のインスタンス。

defclassの文で使用した場合、作成するものは「方法」ではなくプレーンな機能です。クラスまたはインスタンスの属性(Duck.aboutまたはduck.about)を検索すると、この関数は、呼び出し可能なmethodオブジェクト内でラップされ(クラスおよびインスタンスを参照して)、自動的にインスタンス(またはクラス)オブジェクトを処理します関数呼び出しの最初のパラメータとして指定します。https://wiki.python.org/moin/FromFunctionToMethod

あなたのコードスニペットは、あくまで定義されているグローバル名を探し出し、これらの名前が定義されなくなるとすぐに破損するため、誤って「動作」するだけです。これらのグローバル名を再バインドする場合にも、予期しない結果を取得したいNameError

# tail = Tail('long') 
# bill = Bill('wide orange') 
duck = Duck(Bill('wide orange'), Tail('long')) 
duck.about() 

は=>クラッシュは、IE:

tail = Tail('long') 
bill = Bill('wide orange') 
duck1 = Duck(bill, tail) 

tail = Tail('short') 
bill = Bill('norvegian blue') 
duck2 = Duck(bill, tail) 

duck1.about() 

=> Duh、なぜ "短いノルゲーシアンブルー"を印刷しますか?

+0

グローバル変数billはオブジェクトBill( 'norvegian blue')でタグ付けされるようになりました。もう1つの質問ですが、クラス定義内の名前空間の規則は、関数定義内の名前空間の規則と同じですか?たとえば、クラス内に変数を定義すると、ローカル変数として認識されますか? – Nicholas

+0

'class'ステートメントは名前空間を定義しますが、この名前空間は' class'ステートメントが実行されるまで( 'class'ステートメントのブロックが存在するとすぐに)存続し、' class'内で定義された関数は他のステートメント'class'文ブロック内で定義された名前。しかし、この名前空間で定義された名前はクラスの属性になります(カスタムメタクラスによって属性から名前を削除しない限り)。これらの名前は 'self .__ class__ 'を通してアクセスできます。 'または(インスタンス属性がそれらをシャドーしていない場合)直接' 。これはすべて文書化されています... –

1

です。

... 
    def about(self): 
     print('This duck has a', bill.description, 'bill and a', tail.length, 'tail') 
         # these ^^^^       ^^^^ 

# refer to these vvvv 
tail = Tail('long') 
bill = Bill('wide orange') 

だから、あなたの考えはしていません。現在のオブジェクトのbilltailのプロパティを参照する場合は、を省略できます。selfを省略すると、self.billself.tailである必要があります。これらのグローバル変数の名前を変更または削除すると、コードが破損します。

1

これは避けてください。 billabout()は、外側スコープのbill(この場合はグローバルスコープ)を参照します。あなたはそのグローバル変数の値を変更するときに、about()の出力にも影響されます。

>>> tail = Tail('long') 
>>> bill = Bill('wide orange') 
>>> duck = Duck(bill, tail) 
>>> duck.about() 
This duck has a wide orange bill and a long tail 
>>> bill = Bill('DIFFERENT') 
>>> duck.about() 
This duck has a DIFFERENT bill and a long tail 

Duck()に渡されたインスタンス内に格納されているbilltailオブジェクトを参照するために、あなたは常に必要ですself.billおよびself.tailを使用します。

4

明示的には暗黙的であり、selfはメンバー変数にアクセスするときに省略することはできません。

実際には、グローバルスコープの名前を使用します。エラーは、単に他の名前に作成されたオブジェクトを割り当てるトリガするには:

tail1 = Tail('long') 
bill1 = Bill('another') 
duck = Duck(tail1, bill1) 
duck.about() 
関連する問題