この例外が表示されていると思います:
UnboundLocalError: local variable 'meetings' referenced before assignment
ここで経験していることは、実際にはリスト内包表記とは何の関係もありません。このエラーは、最初meetings
に関数の外部で定義したが、関数内で新しい値を割り当てようとしたために発生します。
Python は、関数内で変数に値が割り当てられていることを確認すると、それをその関数に固有の新しい変数として扱います。これにより、関数は、関数の外部から同じ名前を持つ変数にアクセスできなくなります。
内部的には、Python は次のようなことを行っています。
meetings_outside = []
def clean_old():
meetings_inside = [meeting for meeting in meetings_inside if time.mktime(meeting) >= time.localtime()]
これが失敗する理由は理解できます:meetings_inside
はそれ自体で定義されています。Python が の値を検索してmeetings_inside
コンテンツの反復処理を開始しようとすると、まだ値が割り当てられていないため失敗します。
これに対処する方法は、使用している Python のバージョンによって異なり、そこで の初期値meetings
が定義されています。
nonlocal meetings
Python 3 では、関数の先頭に単純に追加できます。meetings
これにより、別の変数を作成するのではなく、という名前の既存の変数を参照していることがわかります。
nonlocal
ただし、おそらくキーワードを持たない Python 2 を使用しています。同じことを行うglobal
キーワードがありmeetings
ますが、モジュールのトップレベルで定義されている場合に限ります。つまり、他の関数またはクラスの外側です。
たとえば、ファイルに他に何もない場合、これは Python 2 で機能します。
輸入時間
meetings = []
def clean_old():
global meetings
meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]
clean_old()
print meetings
[]
meetings
ただし、関数内で定義されているため、これはそうではありません。
import time
def main():
meetings = []
def clean_old():
global meetings
meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]
clean_old()
print meetings
main()
NameError: global name 'meetings' is not defined
この問題を回避する必要があります。最も簡単な方法は、割り当てを次のように変更することです。
meetings[:] = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]
meetings
これは、 内のすべての値を置き換えているが、新しいlist
オブジェクトを作成していないことを Python に伝えます。(:
構文は「スライシング」と呼ばれ、Python チュートリアル で部分的に説明されています。)