2017-06-28 10 views
1

ここには、一貫性のないPython(3.6)動作を示す簡単なファイルがあります。なぜCase 1Case 2が実行されますが、Case 3が最初の2つのケースの合併に過ぎないのに、Case 3が失敗するのはなぜですか?プロパティデコレータを使用したときのPythonの動作が不一致

私はdisの最初の2つのケースの出力を提供しました。

import dis # Python bytecode disassembler 

class A(object): 
    def __init__(self): 
    self.x # In case 2, getting x results in a function call. 

    # CASE 1: Legal 
    def x(self): 
    y 
    pass 

    ''' 
    # CASE 2: Legal 
    @property 
    def x(self): 
    pass 
    ''' 

    ''' 
    # CASE 3: Illegal: 
    @property 
    def x(self): 
    y 
    pass 
    ''' 

if __name__ == '__main__': 
    a = A() 
    dis.dis(A) 

ケース1つのバイトコード:

Disassembly of __init__: 
    5   0 LOAD_FAST    0 (self) 
       2 LOAD_ATTR    0 (x) 
       4 POP_TOP 
       6 LOAD_CONST    0 (None) 
       8 RETURN_VALUE 

Disassembly of x: 
    9   0 LOAD_GLOBAL    0 (y) 
       2 POP_TOP 

10   4 LOAD_CONST    0 (None) 
       6 RETURN_VALUE 

ケース2バイトコード:

Disassembly of __init__: 
    5   0 LOAD_FAST    0 (self) 
       2 LOAD_ATTR    0 (x) 
       4 POP_TOP 
       6 LOAD_CONST    0 (None) 
       8 RETURN_VALUE 
+4

と同じエラーを得た、あなたは何を呼び出していません。 'self.x'は使われていない関数参照です。ケース3の場合、 'self.x'は' x'の定義済みのゲッターを実際に呼び出します。おそらく未定義のグローバル名にアクセスしようとしています。 – chepner

+1

つまり、「関数呼び出しでx結果を得る」というコメントは間違っています。これは、あなたが呼ぶことを怠る関数オブジェクトに評価されます。 –

+0

コメントした行は、この投稿にコメントをつけたものではありませんでした。私が間違っていないとすれば、ケース2のコメントが外され、他のものがコメントアウトされていれば、ラインが適用されると思います。 – awalllllll

答えて

1

ここには矛盾がありません。

a = A()をインスタンス化するとself.xを呼び出し、xの本体を実行する__init__が呼び出されます。その時点では、y inscopeはありません。そのため、例外が発生します。 @のchepnerさんのコメントに

+0

申し訳ありませんが、混乱は何ですか?そして、これはおそらくコメントではなく、答えになるはずです... –

+0

ポスターのコードについて何が矛盾しているのか分かりませんので、私は混乱していますか?私は答えを編集しました。 – csl

1

ありがとう:ケース1では

、あなたは何を呼び出していません。 self.xは使用されていない関数参照 です。ケース3の場合、self.xは実際に定義されたゲッター をxに対して呼び出します。

ケース1は何も呼び出さないので、ケース3にはラインself.xによって引き起こされる動作は、ケース1とは根本的に異なっている - それだけで関数への参照を評価します。

一方、ケース3のself.xは、xメソッドの本体を実行するため、結果は未定義yのエラーとなります。

はchepnerさんのコメント@確認するために、私はケース1で)(a.x走り、ケース1、ケース3

関連する問題