☆Python
_◇モジュール
コードを記述したファイル
⇒拡張子に .py のついたテキストファイル
※あるモジュールで定義されたもの
⇒他のモジュールやmainモジュールにインポートできる
⇒モジュールに記述したコードに対する操作や実行のためにインポート操作が必須
※グローバル変数 __name__
⇒モジュールの中でモジュール名がセットされる
※mainモジュール
⇒対話モードやトップレベルのスクリプトからアクセスできる変数の集まり
※日本語などの非ASCII文字を記述する場合、エンコーディングを記述しておく
例)
#! /usr/bin/env python # coding: utf-8 # -*- coding: utf-8 -*-
_◇パッケージ
モジュールをまとめたもの。フォルダを使う。
⇒ドット区切りのモジュール名を使う
※フォルダをパッケージとして認識させるためには、フォルダ内に
│ __init__.py
という名のファイルを追加する。
※パッケージ内にさらにサブパッケージを設けることができる
⇒階層型のファイルシステムをそのままつかう
⇒各サブパッケージのフォルダにも__init__.pyが必要
※__init__.py
⇒単なる空ファイルでもよい
⇒パッケージの初期化コードを実行させることもできる
※サブパッケージの中のモジュールのインポート
例)
import sound.effects.echo
⇒これに対する参照はフルネームとなる
※__all__
パッケージの__init__.pyのコードが__all__というリストを定義していれば、それは
from パッケージ import *
の際にインポートすべきモジュールのリストとなる
例)
__all__ = [“echo”, “surround”, “reverse”]
_◇インポート
import モジュール名
import パッケージ名(.サブパッケージ名).モジュール名
⇒サブパッケージは複数階層ありえる
⇒import文はモジュール名をそのときのシンボル表にいれる
(モジュールレベル関数は、モジュールのグローバルシンボル表にはいる)
⇒import文は、モジュール内の初期化コード(実行可能な文)を実行する
※インポートしたモジュール内の関数や変数を呼び出す場合、インポートしただけではフルパスで書く必要がある。
※from文を使ったインポート
構文)
from パッケージ import アイテム
構文)
from パッケージ import アイテム.サブアイテム.サブサブアイテム
⇒サブサブアイテム以外はパッケージである必要がある
⇒サブサブアイテムはペッケージでもモジュールでもよいが、クラスや、関数、変数は使えない。
要素呼び出しを簡略化することができる
⇒モジュール内で定義された名前をimportする側のシンボル表にとりこむ
(モジュール名自体はとりこまれない)
構文)
①モジュール内の1要素をインポートする
from モジュール名 import 要素名
②パッケージ内モジュールの1要素をインポートする
from パッケージ名(.サブパケージ名).モジュール名 import 要素名
③パッケージ内のモジュール全体をインポートする
from パッケージ名(.サブパケージ名) import モジュール名
⇒この形式では、要素呼び出しはモジュール名より書く必要がある
④モジュール内の全要素をインポートする
from モジュール名 import *
⇒アンダースコアで始まる以外の名前を全て取り込む
⑤パッケージ内モジュールの全要素をインポートする
from パッケージ名(.サブパケージ名).モジュール名 import *
※関数を頻繁に使う場合
⇒ローカル変数に代入する
例)
fib=fibo.fib
※モジュールはインタプリタセッションに一度しかインポートされない
⇒モジュール変更時にはインタプリタ再起動またはimp.reload()関数が必要
import imp;
imp.reload(モジュール名)
※前置ドットにより、現在モジュールに対する相対インポートも可能
from . import echo
⇒メインモジュールとして使うことがあるモジュールからは絶対インポートする必要がある。
※__path__
__init.py__が実行される前に、__init__.pyが存在するディレクトリ名で初期化される。
_◇モジュール検索パス
モジュールをインポートする際には、モジュールがモジュール検索パスに含まれていないとならない。
※カレントディレクトリは、常にモジュール検索パスに含まれる。
①カレント
②環境変数 PYTHONPATH
③デフォルト検索パス(インストール時にきまる)
⇒スクリプトは標準モジュールと同じ名前にしない
※モジュール検索パスの表示
import sys
sys.path
※モジュール検索パスへの一時的追加
⇒sys.pathはリストなので
sys.path.append(“C:\\パス”)
により追加できる。
_◇モジュールのスクリプトとしての実行
python モジュール.py モジュール引数
のように実行すると、モジュールのコードが実行される
__name__は”__main__”となるのでこれによりスクリプトとして呼んだ場合にのみ実行されるコードを仕込んでおける。
⇒importした場合にはその部分は実行されない
例)
if __name__ == "__main__": import sys 実行関数(sys.argv[1]))
※この機構はモジュールのテストスイート実行によく使われる
_◇コンパイル済のPythonファイル
⇒*.pyファイルの実行時にコンパイル成功すれば書き込みが試みられる。
*.pyc バイトコンパイル済のファイル
⇒該当の.pyファイルの修正時刻と一致しないと実行されない
⇒モジュールについては、pycを持って、pyを持たないようにできる
※プラットフォーム非依存
※動作が速くなるわけでなく、読み込みが速くなるだけ
※compileall
あるディレクトリのモジュール全てについて.pycファイルを生成
_◇名前とオブジェクト
同じオブジェクトに複数の名前を複数のスコープで結合できる
⇒他言語ではエイリアシングと呼ばれることが多い
⇒数値、文字列、タプルなど不変の基本型では意味がない
⇒リストやディクショナリのような可変オブジェクトではポインタ的な操作が可能となる。
_◇名前空間
名前とオプジェクトのマッピング
※通例名前空間はディクショナリとして実装される。(ちがうかもしれない)
例)
│ ビルトイン名 名前空間(⇒インタプリタ起動から終了まで存在
│ builtinsモジュールに属する
│ モジュールグローバル名前空間(⇒モジュール読み込み時に作られる
│ ローカル名前空間
│ 関数がコールされたとき作られ
│ 戻ったり、例外送出したとき思い出せなくなる
⇒別の名前空間の名前とはまったく関係がない
⇒ドットに続くあらゆる名前=属性
⇒モジュール内の名前に対する参照=属性の参照
⇒属性はリードオンリ、リードライトどちらでも可能
⇒リードライト可能なら代入でき、del文での削除も可能
※インタプリタのトップレベルで呼ばれる文(対話、スクリプトどちらでも)
__main__モジュールに属する
_◇スコープ
ある名前空間から直接アクセスできる、プログラムテキスト上の範囲
⇒モジュール名などを前置しない参照で見つけられる
⇒スコープの決定は静的、利用は動的
⇒実行中は常に入れ子のスコープが存在
│ 最初に検索されるローカルスコープ
│ それを取り囲む上位関数の非ローカル、非グローバルな名前
│ モジュールのグローバルなスコープ
│ ビルトイン名の入った名前空間
※グローバル宣言
モジュールのグローバル名前空間への参照と代入が行える
global
⇒有効範囲は一所にバイトコンパイルされたコードに限られる
※nonlocal文(Python 3.x ?)
最内のスコープより外側のものに再結合
⇒nonlocal文で宣言しなければ、ノンローカル変数は読み取り専用
⇒ノンローカル変数に代入のつもりが、同名の新たなローカル変数を作ってしまう
※クラス定義
⇒現在のローカルスコープの中に新たな名前空間を置く
※スコープはプログラムのテキストにより静的に決定されるので、関数をどこからコールしようが、同じモジュールの名前空間に属する
※global(nonlocal)文がないかぎり、代入は常に最内スコープに行う
⇒代入はデータコピーではなく、名前をオブジェクトに結合するだけ
⇒新しい名前の定義も最初はローカルスコープ
⇒global文で、特定の変数がグローバルスコープにあることを示せる
⇒nonlocal文で、特定の変数が自分を取り囲むスコープにあることが示せる
_◇コメント
#記号以降、行末まで
_◇docstring
慣習
1行目は、オブジェクトの短い要約。大文字で始まり、ピリオドで終わる
2行目は空行
以降の行でオブジェクトのコールの仕方や副作用について述べる
_◇行頭の空白とブロック
Pythonでは行頭の空白の数が意味を持つ
⇒字下げされた範囲が一つのブロックとして認識される
※通常半角スペース4個またはTab1個
_◇pass
_◇del
del x
変数を丸ごと、あるいはリストの要素やスライスなどを部分的に消去する
⇒名前空間からxのバインディングを削除する
_◇可変体
mutable
id()を変えずに値が返られるオブジェクト
_◇不変体
immutable
別の値を格納するときは、新しいオブジェクトを生成する必要がある
_◇数値
整数
Python 2.xでは int と longがある。
longのリテラルには末尾にLをつける
Python 3では元のintが廃止され、longがintとなった
小数
⇒floatの値を厳密に知るには
│ float.as_integer_ratio()
整数比で小数を表示する。(厳密)
⇒16進表現(厳密)
│ float.hex()
⇒HEX表現からの値の厳密な再構築
│ float.fromhex(HEX表現)
⇒JavaやC99など同形式表現をサポートする言語とのデータ交換に使える
⇒プラットフォームに非依存
複素数
⇒虚数は接尾辞「j」もしくは「J」を付加する
⇒複素数は(実部+虚部j)とかくか、complex(実部、虚部)と関数で生成する
例)
│ 3+1j
※複素数から実部を取り出す
変数.real
※複素数から虚部を取り出す
変数.imag
_◇数値演算子
()で優先順位をつけることができる
+
–
*
/
│ Python 2.xでは整数、Python 3では浮動小数
※Python2.2以降
from __future__ import division
で整数同士の除算でも小数を返すようになる
//
│ フロア除算
│ 整数の割り算で整数を得て剰余を捨てる場合の演算
│ Python 2.xでも 3でも整数。商の切り捨てを得る。
※Python3
/⇒/の除算で整数同士で割り切れない場合は浮動小数となる
※整数と小数の演算結果は小数となる
** べき乗
※浮動小数点数同士の一致比較
⇒内部表現を考えよ
⇒演算後、round()で丸めることで、非厳密な値同士での比較は一応できる
_◇文字列と文字列演算子
ダブルクウォートもしくはシングルクウォートで括る
※文字列操作の結果をインタプリタは表示する
“”の文字列内には’, ”の文字列内には”を含めることができる
※ \でエスケープすることもできる(ILDE上ではベックスラッシとなる)
※行末にバックスラッシュをおこことで複数行にわたるリテラルを記述できる
⇒リテラル内の改行は\n
※ “””もしくは”’でくくることで改行入りの文字列を記述できる
⇒raw文字列。\nは改行に変換されず、逆に行末の改行はそのまま文字列に含まれる
例
“A\nB”
と
“””A
B”””
は等価
※対話モードで’\n’は改行とならず’\n’と表示される。
⇒printすれば改行される
※文字列連結
例)
“Hello” + ” world”
⇒隣接する文字列リテラルは自動的に連結される
⇒リテラルの場合だけで、文字列演算には作用しない
※文字列繰り返し
*により指定回数繰り返しできる
例)
“aho”*3
※文字列のインデックス付け
文字列の1文字目が0
⇒スライス表記
word[4] 5文字目とりだし
word[0:2] 先頭から2文字とりだし
⇒インデックスの第1文字のデフォルトは0
⇒インデックスの第2文字のデフォルトは文字列のサイズ
word[:2] 最初の2文字
word[2:] 最初の2文字をとった残り
⇒常に
s[:i]+s[i:]==sが成り立つ
⇒インデックスが大きすぎると文字列の長さに置換
⇒上側境界が下側境界より小さいと空文字列が返る
⇒インデックスに負の数を指定した場合、右から数えることを示す
[-2:] 最後の2文字
[:-2] 最後の2文字を除く全て
⇒非負のインデックスではスライスの長さはインデックスの差
※文字列は変更不能なので、インデックス位置への代入はエラー
⇒新たな文字列を生成するように書く
※Python 3
文字列はUnicode
※Python 2.x
文字列は8ビットデータ型。文字列だけでなくバイナリの格納にも使える
ユニコード文字列
u’文字列’
unicode(‘文字列’, ‘エンコーディング名’)
_◇キャラクタ
キャラクタ型は存在しない。
長さ1の文字列を文字として使う
_◇シーケンス
リスト、タプルなど、整数のインデックス値で順序が定まる構造
※シーケンスオブジェクトは同じシーケンンス型をもつオブジェクトと比較可能
⇒アイテム同士の比較は辞書的順序
⇒最初のアイテムが異なれば、それが結果、同じなら2番目以降を再帰的に比較
_◇リスト
シーケンスの一種(数字によるインデックスがつく)
[]の間に複数の値をカンマで区切って記入することでリストになる
⇒最後がカンマでもよい
⇒複数個のデータが順番をもった構造となる
⇒リストのアイテムの型が異なってもよい
⇒文字列と異なりリストの要素は変更できる
⇒リストは入れ子にできる
構文)
[要素1, 要素1, …]
※インデックスを使うことでリストの要素を参照できる
インデックスは0から。また、末尾の要素を-1として終端から数えることもできる
例)参照
xs[0]
⇒リストの範囲を超えるインデックスを指定するとインデックスエラーとなる
例)代入
xs[0] = 9
※スライス
インデックスの範囲を指定してリストを切り出すことができる
⇒第1インデックスの要素から、第2インデックスの一つ手前の要素まで
⇒第1インデックス省略時には0が、第2インデックス省略時にはリスト長が使われる。
⇒リスト範囲を超えたインデックスはエラーとならず、存在範囲のみ返される。まったく存在しない場合は空リスト[]が返る。
リスト[開始位置:終了位置]
例)
[‘a’,’b’,’c’,’d’,’e’][1:3]
>>> [‘b’,’c’]
スライスの置換
a[0:2]=[1, 12]
スライスの削除
a[0:2]=[]
スライスに挿入
a[1:1]=[1, 2]
リストのクリア
a[:]=[]
※連結
リストの連結も+演算子
※指定回数繰り返し
*演算子
_◇リストに関する関数とメソッド
※len関数
リストの長さを調べる
例)
len(xs)
※in演算子
in演算子により、ある値がリストに含まれているか否かを判定できる
例)
1 in [1, 3]
※append(x)メソッド
リストの末尾にアイテムを一つ追加する
例)
xs.append(1)
1を末尾に追加
※extend(L)メソッド
リストの末尾にリストLの全アイテムを追加し、リストを延長する
例)
xs.extend([3,4])
末尾に2要素追加
※insert(i, x)
第1引数で指定された位置にアイテムxを挿入する
※remove(x)
値がxである最初のアイテムを削除
⇒存在しないとエラーとなる
※pop([i])メソッド
位置が指定されれば、その位置のアイテムをリストから削除して返す
指定されないとリストの最後のアイテムを取り出す
例)
xs.pop()
末尾の要素を取り除く
例)
xs.pop(0)
インデックスが0番目の要素を取り除く
※index(x)メソッド
値がxである最初のアイテムのインデックスを返す
例)
xs.index(1)
1が存在する場所の最初のインデックスを取得する。見つからない場合はValueError
※count(x)
リストの中のxの個数を返す。
※sort()メソッド
リストをインプレースでソートする
例)
xs.sort()
※reverse()
リストの要素をインプレースで逆順にする
_◇リスト操作
①スタックとして使う
PUSH操作⇒append()
POP操作⇒pop() インデックスは指定しない
②キューとして使う
追加⇒append()
取り出し⇒pop(0)
③リスト内包
シーケンスからリストを生成する
⇒元のリストに操作を加えた新たなリストを作る
⇒元のリストから条件にあうリストを取り出す
構文)
[ 式 for節 オプショナルなfor節またはif節]
例)
リストの全要素を3倍する
[3*x for x in vec]
リストの各要素からリストをつくる
[[x, x**2] for x in vec]
リストの各要素からタプルをつくる
[(x, x**2) for x in vec]
ループの入れ子
[x*y for x in vec1 for y in vec2]
例)
if節をつかった仕分け
[3*x for x in vec if x > 3]
④リストで作られた行列の転置
mat = [ [1,2,3], [4,5,6], [7,8,9], ] print [[row[i] for row in mat] for i in [0, 1, 2]]
_◇タプル
カンマで区切られた値からなる。
通常は丸カッコで囲まれるが、丸カッコで囲わなくてもタプルにすべきものはタプルとなる。
⇒座標やレコードなどに使える
⇒タプルはリストと異なり不変
例)
t = 1, 2, 3
※アイテム数が0や1のタプルには区切りのカンマがないので
①空のタプル ()
②要素数1のタプル 値,
※タプルパッキング(丸カッコで囲わなくてもタプルになること)
※シーケンス・アンパッキング
タプルを開いて別々の変数に代入する
例)
x, y, z = t
_◇集合(set)
1個以上の要素を持つ集合は{}中かっこで生成できる
または set() 関数で空集合を含む集合を定義できる
例)
集合として定義
s = {‘a’, ‘b’, ‘a’, ‘c’}
⇒’a’は重複しているが、集合なので重複は除かれる
⇒set()関数にリストを与えれば、重複が除かれて集合が生成される
⇒in により存在判定ができる
‘a’ in s
※set関数に文字列ひとつだけを与えると、文字集合が作られる
※集合に対する-演算子
集合1-集合2
集合1の要素の中で集合2に存在しないもの
※|演算子
集合の和
※&演算子
集合の積
※^演算子
集合の排他的論理和
※リストと同様に内包構文が使える
_◇ディクショナリ
辞書
シーケンスと異なり数字によるインデックスはつかない
要素に順序はない。キーと値のペアでデータが格納され、キーをつかってデータの出し入れをすることができる。キーは一意でなければならず、変更不能なオブジェクトでないとならない(リストや辞書は変更可能オブジェクトなのでキーにはなれない)
⇒不変型のオブジェクトのみを含むタプルはキーとして使える
⇒からの中カッコ対{}は空のディクショナリとなる
書式)
キーと値のペアをコロンでつないだものをカンマで区切って連ね、中かっこでくくる
{key1:val1, key2:val2, …}
※dict関数
キーと値ペアのタプルのリストから辞書を作る
例)
dict([(‘a’,1),(‘b’,2),(‘c’,3)])
例)
dict(a=1, b=2, c=3)
キーワード引数
dist(a=1, b=2, c=3)
※キーによる値の取得
[]の中にキーを置いてアクセスする。キーが存在しなければKeyErrorとなる
※値の更新
キーを指定して代入すれば辞書の値が更新される。
⇒存在しないキーに対して代入すると新しくキーが作られる。
※キーの削除
del文による
⇒存在しないキーを削除しようとするとKeyErrorとなる
例)
del d[‘a’]
※キーの存在の確認
in演算子による。値が辞書オブジェクトに含まれていればtrueを返す
構文)
値 in 辞書オブジェクト
例)
“B” in a
※len関数
辞書のキーの数を返す
※get()メソッド
キーによる値の取得を行う。キーが存在しなかった場合、None(数値でも文字列でもない特殊な値)が得られる。第2引数に値を指定すれば、Noneの代わりに他の値を得ることもできる。
構文)
辞書オブジェクト.get(key[, default_value])
※keys()メソッド
キーの一覧を得る。
Python 2.X リストで得られる
Python 3 リストで得るためにはkeys()で得た値をlist()関数に渡す必要あり
⇒Python3のkeysが返すのは「シクショナリ・ビュー」オブジェクトである。存在テストや反復の対象にはなるが、中身は元のディクショナリのあくまでビュー
※values()メソッド
値の一覧を得る。
Python 2.X リストで得られる
Python 3 リストで得るためにはvalues()で得た値をlist()関数に渡す必要あり
※items()メソッド
キー:バリューペアの一覧を得る。
Python 2.X リストで得られる
例)
for k, v in s.items():
│ print k, v
Python 3 リストで得るためにはitems()で得た値をlist()関数に渡す必要あり
※キーのソート
keywordsに辞書が入っているとして
sorded(keywords.keys())
※辞書内包
例)
{x: x**2 for x in (2, 4, 6)}
_◇コンテナ
複数の要素を入れられる要素
⇒リスト、タプルなど
_◇真偽値
0でない整数…真
0…偽
_◇比較演算子
比較演算子の優先順位は全て同等、かつ数値演算子より低い
⇒異なる型同士であっても、適切な比較メソッドがあれば比較できる。そうでない場合は、TypeError例外が発生する
<
>
==
<=
>=
!=
※in, not in
シーケンスに値が存在するか、存在しないか
※is, is not
2つのオブジェクトが完全に同一であるか否か
※比較の連鎖
例)
1 < a < 3
_◇ブール演算子
ブール演算子の優先順位は比較演算子よりも低い
ブール演算子の中ではnotが高く、orが低い
and
or
not
※andとorは 短絡演算子
⇒評価は左から右、結論が決定したところで評価をやめる
_◇代入
= 代入演算子
⇒プロンプトで代入しても答えは表示されない
⇒代入は複数の変数に同時に行える
⇒Cとは異なり、式の中での代入はできない
変数には数値、文字列、リストなどを代入できる
例)
x = 2
x=y=z=0
※多重代入
例)
│ a, b = 0, 1
⇒代入が行われるまでにまず右辺式が評価される
_◇変数の定義
変数は使用前に値を代入することで定義しなければならない
未定義の変数をアクセスするとNameErrorが発生する
_◇繰り返し for
※多言語のfor より foreachに近い
⇒シーケンスに対して、シーケンス内の順序で反復を書ける
構文)
for 変数 in コンテナ: 繰り返し処理ブロック
例)
fruits = ["Apple", "Orange", "Banana"] for fruit in fruits: print fruit
※反復対象のシーケンス(リストなど)をループ内で改変するのは安全でない
⇒ループ制御のためにシーケンスのコピーをとって反復する
例)
for x in a[:]: ...
※range()関数
⇒等差数列を生成する
⇒繰り返しの回数制御に使う。数値のリストを生成する。階差を指定しないと1となる
⇒終了値はリストに入らない
構文)
range(開始,終了,階差)
例)
for i in range(5): print i
⇒range(2, 5)などとすることで開始の数を指定できる
⇒シーケンスのインデックスで反復をかけたいとき
例)
for i in range(len(a)): ...
※enumerate()関数
位置インデックスと対応値を同時に得ることができる
for i, v in enumerate(lis): print i, v
※zip()関数
2つ以上のシーケンスについて両者のエントリをペアにして同時にループをかける
for q, a in zip(qq, aa): ...
※reversed()
シーケンスを逆順とする
※sorted()
元のシーケンスを保存し、新たにソート済のリストを返す
_◇繰り返し while
構文)
while 条件 : 繰り返し処理ブロック
_◇breakとcontinue, else
※break
│ 最も内部のforかwhileループを抜ける
※continue
│ 最も内部のforかwhileループの次の反復へ進める
※else
⇒forの場合、リストを使い終わった後で実行
⇒whileの場合、ループ終了後に実行
⇒breakで抜けた場合は実行されない
_◇pass
構文的に文が必要なのに、プログラム的には何もする必要がないときに使う。
_◇条件分岐 if
※他言語のswitch, caseの代わりともなる
構文)
if 式1: 式1がTrueのときの処理 elif 式2: 式2がTrueのときの処理 else: いずれの式もTrueでなかったときの処理
⇒elifはいくつでも記述できる
⇒elif, elseは必須ではない
※in
シーケンスが指定の値を含むかどうかを判定する
例)
if ok in ('y', 'ye', 'yes'): ...
_◇比較演算子
==
!=
>
<
>=
<=
not
and
or
_◇反復子
iterator
※コンテナオブジェクトの多くはfor文でループできる
for element in [1, 2, 3]: print(element) for element in (1, 2, 3): print(element) for key in {'one':1, 'two':2}: print(key) for char in "123": print(char) for line in open("myfile.txt"): print(line)
※仕組み
①for文⇒コンテナオブジェクトのiter()をコール
②iter()は反復子オブジェクトを返す
③反復子オブジェクトにはコンテナ要素に一つづつアクセスする__next()__メソッドがある。要素が尽きるとStopIteration例外を送出する
④StopIteration例外によりfor文は終了する
反復子の例)
s=’abc’
it=iter(s)
next(it)
_◇ジェネレータ
反復子をつくるための仕組み
通常の関数と同様に書くが、データを返すところでyieldを使う
⇒これにより通常の関数と異なり、next()がコールされるたびに、前回の環境の最後に実行した文に戻る(ローカル変数と実行状態が自動保存される)
⇒__iter__()と、__next__()が自動的に生成される
⇒終了時に自動的にStopIterationを送出する
例)
def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] for char in reverse('golf'): print char
_◇ジェネレータ式
リスト内包に似た構文でコンパクトなジェネレータを作れる
例)
sum(i*i for i in range(10)
※内積をもとめる
xvec = [10, 20, 30]
yvec = [7, 5, 3]
sum(x*y for x,y in zip(xvec, yvec))
※3角関数表をつくる(ディクショナリ)
from math import pi, sin
sine_table = {x: sin(x*pi/180) for x in range(9, 91)}
※ページの中の重複しない単語
unique_words = set(word for line in page for word in line.split())
_◇内包
chmprehension
①リスト
[ x for x in stuff]
②ディクショナリ
{ k:v for k, v in stuff}
③セット
{ x for x in stuff*}
④ジェネレータ式
( x for x in stuff)
※基本形
結果の形 for 取るデータ in 元データ [取るデータにかかる条件節if]