2017-11-10 15 views
6

ここでは、Pythonの内部のクラス変数 リストの理解にアクセスできません。Python 3 - クラスの変数が定義されていません

class Student: 
    max_year = 18 
    year_choice = [i for i in range(100) if i > max_year] 

    def __init__(self, name): 
    self.name = name 
    print (self.year_choice) 

Student('Blah') 

しかし、それは、Python 2に

../workspace$ python student.py 
[19, 20, 21, 22, 2.... 99] 

を正常に動作しかし、私は声明

の下 を変更した場合、これをデバッグするのはPython 3に

../workspace$ python student.py 
File "student.py", line 18, in <listcomp> 
year_choice = [i for i in range(100) if i > max_year] 
NameError: name 'max_year' is not defined 

をエラーを取得しています[i for i in range(100) if i > max_year]

この

[i for i in range(max_year)] # don't look too much into it ;) 

作業罰金に

。 内部でクラス変数にアクセスできない理由/elseリストの理解

+0

これは大変奇妙です。 ;)また、リストcompの中の 'if'とは何の関係もありません。これはうまくいきません: '[max_year-i for i in range(max_year)]' –

+1

はい、@py_dudeから答えます。self.max_yearを定義できます。このクラスのクラスとインスタンスと共有されています。この例だけではありません。しかし、ここで私はクラス変数にアクセスできない理由を知りたいと思っています。 – ramganesh

+0

良い質問ですが、それはまだ重複しています;-) –

答えて

4

この行は

year_choice = [i for i in range(100) if i > max_year] 

のPython 2での作品ではなく、Pythonの3のその理由は、Python 3のリスト内包表記で新しいスコープを作成し、max_yearクラス属性は、そのスコープではないということです。 Python 2では、リスト内包は新しいスコープを作成せず、周囲のコードのコンテキストで実行されます。これはもともとパフォーマンス上の理由から行われましたが、多くの人が混乱していると感じました。したがって、Python 3ではリストの解説をジェネレータの式に合わせて変更し、解説を設定して補完しました。

AFAIKでは、メソッド内ではなく、クラスの外部コンテキストで実行されているリスト内包の内部でクラス属性にアクセスする簡単な方法はありません。その時点でStudentクラスが存在しないため、Student.max_yearで参照することはできません。

しかし、とにかくそのリストの理解があるという点は本当にありません。よりコンパクトに、より効率的に必要なリストを作成することができます。例:このコードは、Python 2とPython 3に同じ出力を生成

[19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] 

class Student(object): 
    max_year = 18 
    year_choice = list(range(max_year + 1, 100)) 

    def __init__(self, name): 
     self.name = name 
     print (self.year_choice) 

Student('Blah') 

出力

Iは

class Student(object): 
にクラス署名を変更しました

これにより、Python 2で新しいスタイルのクラスが作成されます( Python 3すべてのクラスは新しいスタイルです)。


[i for i in range(max_year)]は、この制限を回避できるという理由は、反復子は、リストの内包表記を実行し、一時的な関数の引数として渡されrange(max_year)から作成されていることです。したがって、次のコードと同じです。

class Student(object): 
    max_year = 18 
    def _listcomp(iterator): 
     result = [] 
     for i in iterator: 
      result.append(i) 
     return result 

    year_choice = _listcomp(iter(range(max_year + 1, 100))) 
    del _listcomp 

    def __init__(self, name): 
     self.name = name 
     print(self.year_choice) 

Student('Blah') 

この説明については、Antti Haapalaに感謝します。

関連する問題