Pythonではすべての値がデータ型を持っているにもかかわらず、 変数のデータ型を宣言する必要はない。
これはどういう仕組みで動いているんだろう? Python は、それぞれの変数について、 もともとの代入がなされたときに何の型であるかを把握し、 それを内部的に追跡している。
Pythonは数多くのネイティブデータ型を持っている。 重要なものは以下。
Pythonではあらゆるものがオブジェクトなので、モジュール・関数・クラス・メソッド・ファイル、そしてコンパイルされたコードといった型すら存在する。
「モジュール」は、名前を持つ( .__name__
)、
関数は .docstrings()
を持つ、
ブール値は真または偽のどちらかを表す。 Pythonは、True, Falseと分かりやすく命名された2つの定数を持っており、これらはブール値を直接代入するために使える。
式を評価した結果もブール値になりうる。 特定の箇所(たとえばif文)では、式を評価した結果がブール値になることが要求される場合もある。 このような箇所は、 ブール値のコンテクスト と呼ばれる。 そこでは事実上どんな式でも使うことができ、 Python は、その式の真偽値を決定しようと試みる。
例として、
変数size
は整数で、0
も整数、
そして<
は数値演算子だ。
式size < 0
の結果は常にブール値になる。
size = 1
size < 0
False
size = 0
size < 0
False
size = -1
size < 0
True
Python 2から残されたいくつかの古い問題のために、ブール値を数値として扱うこともできる。
True + True
2
True - False
1
True * False
0
True / False
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-7-dcacc0b7b97e> in <module>() ----> 1 True / False ZeroDivisionError: division by zero
Pythonは、整数と浮動小数点数の両方をサポートしている。この2つを区別するための型宣言は存在せず、Pythonは小数点が存在するかしないかで両者を区別する。
値や変数の型を調べるにはtype()関数
が使える
type(1)
int
値や変数の型が特定の型かどうかを調べるには、
isinstane()関数
が使える。
isinstance(1, int)
True
1 + 1
2
intをfloatに加えるとfloat になる。 Pythonはintをfloatに型強制 (coercion) してから加算を行い、 その結果としてfloatを返す。
1 + 1.0
2.0
type(2.0)
float
いくつかの演算子(加算など)は必要に応じて整数を浮動小数点数に型強制する。自分でこの型強制を行うことも可能。
float()関数
を呼び出すことで、明示的にintをfloat へ型強制できる。
float(2)
2.0
int()関数
を呼び出すことで、明示的にfloatをintに型強制できる。
int(2.0)
2
int()関数
は、切り捨てを行う。
int(2.5)
2
int()関数は、負数を0の方向へ向けて切り捨てる。 これは正しい切り捨て関数で、床関数 (floor function) ではない。
int(-2.5)
-2
浮動小数点数は小数第15位まで正確。
1.12345678901234567890
1.1234567890123457
type(1000000000000000)
int
詳細はpep 237
python3 ではsys.maxint
はmaxsize
に置き換えられている。
import sys
sys.maxsize
9223372036854775807
11 / 2
5.5
結果が正の数の場合は、整数への切り捨て(四捨五入ではない)とみなすことができるが、これについては注意が必要。
11 // 2
5
負の数を整数除算する場合、//演算子は最も近い整数に繰り「上げる」。数学的に言えば、−6は−5より小さいので「繰り下げ」というべきだが、−5に切り捨てられることを期待していると足もとをすくわれる。
-11 // 2
-6
//演算子は常に整数を返すわけではない。 分子や分母のどちらか一方でもfloatの場合は、 なお結果を最も近い整数に丸めてくれるのだが、 実際の戻り値はfloat で返される。
11.0 // 2
5.0
**演算子は「べき乗」を意味する。 つまり$11^2 = 121$。
11 ** 2
121
%演算子は整数除算の余りを返す。 11を2で割ると5余り1になるので、ここでの結果は1となる。
11 % 2
1
Python 3では、
/演算子
は常に浮動小数点数の除算を行う。
詳細はpep 238。
分数も扱える。
分数を使うために、fractionsモジュールをインポート。
import fractions
fractions
<module 'fractions' from 'C:\\Miniconda3\\lib\\fractions.py'>
分数を定義するには、Fractionオブジェクトを作って分子と分母を渡す。
x = fractions.Fraction(1, 3)
x
Fraction(1, 3)
分数をつかった普通の数学的演算ならなんでもできる。 演算結果は新しいFractionオブジェクトとして返される。
$$ 2 * \frac{1}{3} = \frac{2}{3} $$x * 2
Fraction(2, 3)
Fractionオブジェクトは自動的に約分される。
$$ \frac{6}{4} = \frac{3}{2} $$fractions.Fraction(6, 4)
Fraction(3, 2)
Pythonは、分母がゼロの分数が作成されないようにうまくやってくれる。 zero除算エラーが出る。
fractions.Fraction(0, 0)
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-30-b2c38c7f647e> in <module>() ----> 1 fractions.Fraction(0, 0) C:\Miniconda3\lib\fractions.py in __new__(cls, numerator, denominator, _normalize) 184 185 if denominator == 0: --> 186 raise ZeroDivisionError('Fraction(%s, 0)' % numerator) 187 if _normalize: 188 if type(numerator) is int is type(denominator): ZeroDivisionError: Fraction(0, 0)
Pythonでは基本的な三角法も行える。
math
は、円周率$\pi$ のために定数を用意している。
import math
math
<module 'math' (built-in)>
math.pi
3.141592653589793
math
には基本的な三角関数が全部入っている。
例えば$\sin()$, $\cos()$, $\tan()$ といったものや、
$\arcsin()$ のような派生形も入っている。
math.sin(math.pi / 2)
1.0
Pythonは無限の精度を持たないことに注意。 $\tan(\frac{\pi}{4})$ は、 1.0を返すべきなのに、0.99999999999999989が返ってきてしまう。
math.tan(math.pi / 4)
0.9999999999999999
数値はif文のようなブール値のコンテクストで使うことができる。
def is_it_true(anything):
if anything:
print("yes, it's true")
else:
print("no, it's false")
is_it_true(1)
yes, it's true
is_it_true(-1)
yes, it's true
is_it_true(0)
no, it's false
ゼロでない浮動小数点数は真であり、0.0は偽。 これには注意しなければならない。 わずかな丸め誤差が発生した場合(前の節で見たように、これは起こりうる)、Pythonは0ではなく0.0000000000001を評価することになり、 その結果Trueが返されてしまう。
is_it_true(0.1)
yes, it's true
is_it_true(0.0)
no, it's false
分数もブール値のコンテクストで使うことができる。
Fraction(0, n)
はすべての n について偽になる。
それ以外の分数は真。
is_it_true(fractions.Fraction(1, 2))
yes, it's true
is_it_true(fractions.Fraction(0, 1))
no, it's false
PythonのリストはJavaの配列を遙かに超えたもの。 ArrayListクラスに似ている。 これは任意のオブジェクトを格納できるし、 新しい要素を追加するとサイズが動的に拡張される。
カンマで区切って並べた値を、角括弧で包む。
要素が元の順番を保持していることに注意。 リストは順序づけられた要素の集合。
a_list = ['a', 'b', 'mpilgrim', 'z', 'example']
a_list
['a', 'b', 'mpilgrim', 'z', 'example']
リストはインデックスが0から始まる配列のように扱うことができる。 空でないリストの先頭の要素は常にa_list[0] 。
a_list[0]
'a'
a_list[4]
'example'
負のインデックスは、配列の後ろ側から逆順に数えて要素にアクセスする。 空でないリストの最後の要素は常にa_list[-1]になる。
a_list[-1]
'example'
負のインデックスが理解しにくいのなら:
a_list[-n] == a_list[len(a_list) - n]
。
つまりこのリストでは、a_list[-3] == a_list[5 - 3] == a_list[2]
。
a_list[-3]
'mpilgrim'
リストを定義したら、そのリストの任意の一部分を新しいリストとして取得できる。これはリストのスライスという。
a_list
['a', 'b', 'mpilgrim', 'z', 'example']
戻り値は、
a_list[1:3]
['b', 'mpilgrim']
スライスは、スライスインデックスの一方または両方が負の数でも動作する。 これは次のように考えると良いかもしれない: リストを左から右へ読み、
a_list[1:-1]
['b', 'mpilgrim', 'z']
a_list[0:3]
['a', 'b', 'mpilgrim']
左側のスライスインデックスが0のときは、これを省略できる。
つまり、a_list[:3]
は、始点のインデックスが暗黙に0 とみなされるので、a_list[0:3]
と同じ。
a_list[:3]
['a', 'b', 'mpilgrim']
右側のスライスインデックスがリストの長さと同じである場合は、これを省略できる。つまりa_list[3:]は、このリストが5つの要素から構成されているので、a_string[3:5]と同じになる
この5つの要素を持つリストでは、
a_list[:3]
は最初の3要素を返し、
a_string[3:]
は最後の2要素を返す。
実際に、リストの長さにかかわらず、
a_list[:n]
は常に最初の n 個の要素を返し、
a_list[n:]
はその残りを返す。
a_list[3:]
['z', 'example']
両方のスライスインデックスが省略された場合は、リストのすべての要素が含まれる。しかし、これは元の a_list 変数とは異なる。これは、たまたますべて同じ要素を持った新しいリストなのだ。だから、a_list[:]はリストの完全なコピーを作るための簡易な方法として使える。
a_list[:]
['a', 'b', 'mpilgrim', 'z', 'example']
a_list[:6]
['a', 'b', 'mpilgrim', 'z', 'example']
要素をリストに追加する方法は4つある。
a_list = ['a']
a_list
['a']
+演算子はリストを結合して新たなリストを作る。
メモリの使用量が問題となるような場合には、このリストの結合によって新たなリストがメモリ上に作成されることに注意すること。 この場合、その新しいリストはすぐに既存の変数a_listへ代入される。 つまり、この行は実際には
という2つのステップから成り立っており、巨大なリストを扱うときには(一時的に)大量のメモリを消費する可能性がある。
リストは任意のデータ型の要素を含むことができ、1つのリストの要素がすべて同じ型である必要はない。
a_list = a_list + [2.0, 3]
a_list
['a', 2.0, 3]
append()メソッドはリストの末尾に要素を1つ追加。
a_list.append(True)
a_list
['a', 2.0, 3, True]
extend()
メソッドは1つの引数としてリストをとり、
引数として与えられたリストの各要素を元のリストへ追加する。
a_list.extend(['four', 'Ω'])
a_list
['a', 2.0, 3, True, 'four', 'Ω']
insert()
メソッドは、1つの要素をリストに挿入する。
1つ目の引数は、挿入によって「位置がずらされる最初の要素のインデックス」。
a_list.insert(0, 'Ω')
a_list
['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
append()とextend()の違い
a_list = ['a', 'b', 'c']
a_list
['a', 'b', 'c']
extend()
メソッドは、
単一の引数として常にリストを取り、そのリストの各要素をa_listへ追加する。
a_list.extend(['d', 'e', 'f'])
a_list
['a', 'b', 'c', 'd', 'e', 'f']
len(a_list)
6
a_list[-1]
'f'
append()メソッドも引数を1つだけとるが、その引数はどんなデータ型でもいい。
a_list.append(['g', 'h', 'i'])
a_list
['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']]
6つの要素を持つリストに対してリストを加える (append) と、 結果は…… 7つの要素を持つリストになる。
len(a_list)
7
なぜなら最後の要素(今加えたもの)はリスト自体のため。 リストはどんなデータ型でも含むことができるので、リストが他のリストを含むこともできる。これは望む結果かもしれないし、そうでないかもしれない。
a_list[-1]
['g', 'h', 'i']
a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
a_list
['a', 'b', 'new', 'mpilgrim', 'new']
count()
メソッドは指定された値がリストの中に何回出現するかを数える。
a_list.count('new')
2
リストの中に特定の値があるかどうかを知りたいだけの場合は、
count()
メソッドよりもin演算子の方がわずかながら処理が早い。
リスト中にその値が何回現われるのかは教えないため。
in演算子は、常にTrueまたはFalseを返す。
'new' in a_list
True
'c' in a_list
False
値がリストのどこにあるのかを知る必要がある場合は、
index()
メソッドを呼び出だす。
デフォルトでは、このメソッドはリスト全体を検索するが、
a_list.index('mpilgrim')
3
a_list.index('new')
2
値がリストから見つからない場合、
index()
メソッドは例外を送出する。
a_list.index('c')
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-74-4e77f8c6f6f7> in <module>() ----> 1 a_list.index('c') ValueError: 'c' is not in list
index()メソッドは、値をリストから見つけ出せなかった場合に例外を送出する。 これは他の多くの言語と際だって異なる点。 他の多くの言語はここで無効なインデックス(例えば-1)を返す場合が多い。 こうすれば、後の方で密やかに奇妙な振る舞いを引き起こすのではなく、 問題の根源でクラッシュしてくれる。
Pythonでは、そもそも「-1」がリストの有効なインデックスになる。
リストから要素を取り除くのにもいくつかの方法がある。
a_list = ['a', 'b', 'new', 'mpilgrim', 'new']
a_list[1]
'b'
特定の要素をリストから削除するには、del文
が使える。
del a_list[1]
a_list
['a', 'new', 'mpilgrim', 'new']
a_list[1]
'new'
インデックスの位置が分からないときは、 代わりに値を指定することで要素を取り除くことができる。
remove()
メソッドでもリストから要素を取り除ける。
remove()
メソッドは値を受け取り、それで最初に見つかったものをリストから取り除く。
a_list.remove('new')
a_list
['a', 'mpilgrim', 'new']
a_list.remove('new')
a_list
['a', 'mpilgrim']
remove()
メソッドは好きなだけ呼び出すことができるが、
リストの中に存在しない値を取り除こうとすると、このメソッドは例外を出す。
a_list.remove('new')
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-80-c2064dc3d02e> in <module>() ----> 1 a_list.remove('new') ValueError: list.remove(x): x not in list
pop()
メソッドは、リストから要素を取り除くもう一つの方法。
リストのpop()メソッドを引数なしに呼び出すと、 リストの最後の要素が削除されて、削除された値が返される。
a_list = ['a', 'b', 'new', 'mpilgrim']
a_list.pop()
'mpilgrim'
a_list
['a', 'b', 'new']
任意の要素をリストからpopできる。これにはインデックスをpop()メソッドに渡すだけ。
a_list.pop(1)
'b'
a_list
['a', 'new']
a_list.pop()
'new'
a_list.pop()
'a'
空リストのpop()メソッドを呼び出すと、例外が出される。
a_list.pop()
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-87-3bc9ba441032> in <module>() ----> 1 a_list.pop() IndexError: pop from empty list
pushの代わりが.append()
になる
リストはif文のような ブール値のコンテクストでも使うことができる。
ブール値のコンテクストでは、空のリストは偽。
is_it_true([])
no, it's false
要素を1つでも持つリストは真。
is_it_true(['a'])
yes, it's true
is_it_true([False])
yes, it's true
タプルはイミュータブルなリスト。 いったん作成されたタプルは、どんな手段によっても変更できない。
タプルはリストと同じような方法で定義するが、 要素の集合の全体を角括弧ではなく丸括弧「()」で包む点が異なる。
a_tuple = ("a", "b", "mpilgrim", "z", "example")
a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
a_tuple[0]
'a'
リストと同様に、負のインデックスはタプルの後ろ側から数えられる。
a_tuple[-1]
'example'
リストと同様に、スライスすることもできる。リストをスライスすると新しいリストが得られるように、タプルをスライスすると新しいタプルが得られる。
a_tuple[1:3]
('b', 'mpilgrim')
タプルとリストの大きな違いは、タプルは変更ができないという点だ。専門用語ではこれを、タプルは ** イミュータブル (immutable) ** であると言う。
リストはappend(), extend(), insert(), remove(), pop()
などのメソッドを持っているが、タプルはこれらのメソッドを持っていない。
a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
a_tuple.append("new")
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-96-1b46e9a44545> in <module>() ----> 1 a_tuple.append("new") AttributeError: 'tuple' object has no attribute 'append'
a_tuple.remove("z")
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-97-e1d2acaf7dc7> in <module>() ----> 1 a_tuple.remove("z") AttributeError: 'tuple' object has no attribute 'remove'
タプル中の要素を検索することはできる。
a_tuple.index("example")
4
in演算子を使って、要素がタプルに含まれているかどうかを調べることもできる。
"z" in a_tuple
True
タプルの利点
タプルはリストよりも高速。変更を加える予定のない集合を定めて、それをイテレートするだけのつもりなら、リストの代わりにタプルを使うとよい。
変更の必要がないデータを「書き込み保護」すれば、コードはもっと安全なものになる。タプルをリストの代わりに使うことは、データが不変であることを示す暗黙的なassert文があるようなものであり、それを上書きするには特別の意図(と特定の関数)が要求される。
ある種のタプル(具体的に言えば、文字列とか数字とか他のタプルとかいったようなイミュータブルな値からなるタプル)は辞書のキーとして使える。リストはイミュータブルではないので、辞書のキーとしては決して使うことができない。
タプルはリストに変換できるし、その逆もできる。
list()
関数はタプルを引数にとってリストを返す。実質的には、
を行うと考えることができる。
a_tuple_list = list(a_tuple)
a_tuple_list
['a', 'b', 'mpilgrim', 'z', 'example']
type(a_tuple_list)
list
a_list_tuple = tuple(a_tuple_list)
a_list_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
type(a_list_tuple)
tuple
タプルはif文のようなブール値のコンテクストで使うことができる。
ブール値のコンテクストでは、空のタプルは偽。
is_it_true(())
no, it's false
要素を1つでももつタプルは真。
is_it_true(('a', 'b'))
yes, it's true
is_it_true((False,))
yes, it's true
1つの要素からなるタプルを作るには、 値の後にカンマ「,」を置かなくてはならない。 もしこのカンマがないと、Pythonは余分な括弧があるだけだと見なしてしまう。 これはエラーにはならないが、タプルは作成されない。
type((False))
bool
type((False,))
tuple
Pythonでは、タプルを使って複数の値を一度に代入できる。
一方をもう一方へ代入すると、vの各々の値が、順番通りに各々の変数へ代入される。
v = ('a', 2, True)
(x, y, z) = v
x
'a'
y
2
z
True
これにはあらゆる使い道がある。
仮に、連続する数値に名前を付けたいとしよう。
組み込みの range()
関数と多値代入を使うことで、連続する値を素早く代入することができる。
組み込みのrange()関数は、整数のシーケンスを構築する。
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAYが、ここで定義している変数だ
(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
MONDAY
0
TUESDAY
1
SUNDAY
6
多値代入は、複数の戻り値を返す関数を作るためにも使える。 これをするには単純に、すべての戻り値を含むタプルを返せばいい。 呼び出し元は、返されたタプルを1つのタプルとして扱うこともできるし、個別の変数に値を代入することもできる。
多くのPythonの標準ライブラリがこれを行っている。
集合は一意な値を詰めた「袋」であり、その要素は順序づけされない。 1つの集合の中には、イミュータブルなデータ型の値なら何でも含めることができる。
2つの集合を作れば、それらを使って和集合・積集合・差集合といった標準的な集合演算を行うこともできる。
1つの値を持った集合を作るには、その値を波括弧 ({}) の中に入れればいい。
a_set = {1}
a_set
{1}
type(a_set)
set
a_set = {1, 2}
a_set
{1, 2}
リストから集合を作ることもできる。
リストから集合を作るには、set()関数を使えばよい
a_list = ['a', 'b', 'mpilgrim', True, False, 42]
a_set = set(a_list)
a_set
{False, True, 42, 'mpilgrim', 'b', 'a'}
a_list
['a', 'b', 'mpilgrim', True, False, 42]
空の集合を作ることができる。
空の集合を作るには、set()を引数なしに呼び出せばいい。
空の集合は少し変わった表現 set()
で表示される。
a_set = set()
a_set
set()
type(a_set)
set
この集合は要素を持たない。
len(a_set)
0
二つの波括弧で空の集合を作ることはできない。これは実際には空の集合ではなく、「空の辞書」を作ってしまう。
not_sure = {}
type(not_sure)
dict
集合に値を追加するには2つの異なる方法がある。
add()メソッドは単一の引数(どんな型でもよい)をとり、与えられた値を集合に追加する。
a_set = {1, 2}
a_set.add(4)
a_set
{1, 2, 4}
len(a_set)
3
集合なので、既にその集合に含まれている値を追加しようとしても、何も起こらない。
a_set.add(1)
a_set
{1, 2, 4}
len(a_set)
3
a_set = {1, 2, 3}
a_set
{1, 2, 3}
update()メソッドは1つの引数として集合をとり、その集合のすべての要素を元の集合に追加する。
a_set.update({2, 4, 6})
a_set
{1, 2, 3, 4, 6}
実際にはupdate()メソッドは任意の数の引数と共に呼び出すことができる。 2つの集合と共に呼び出すと、update()メソッドは各々の集合の各要素を元の集合に追加する。
a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})
a_set
{1, 2, 3, 4, 5, 6, 8, 9, 13}
update()メソッドは、リストのようにいくつもの異なるデータ型から構成されるオブジェクトを受け取ることができる。リストと共に呼び出されると、update()メソッドはリストのすべての要素を元の集合に追加する。
a_set.update([10, 20, 30])
a_set
{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
集合から値を取り除くには3つの異なる方法がある。 始めの2つは
a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
a_set
{1, 3, 6, 10, 15, 21, 28, 36, 45}
discard()
メソッドは引数として1つの値を受け取り、その値を集合から取り除く。
a_set.discard(10)
a_set
{1, 3, 6, 15, 21, 28, 36, 45}
集合に存在しない値を引数としてdiscard()
メソッドを呼び出したときは、何も行われない。エラーも起きない。(差集合)
a_set.discard(10)
a_set
{1, 3, 6, 15, 21, 28, 36, 45}
remove()
メソッドも同じく引数として1つの値を受け取り、その値を集合から取り除く。
a_set.remove(21)
a_set
{1, 3, 6, 15, 28, 36, 45}
値が集合の中に存在しない場合は、remove()メソッドはKeyError例外を送出する。
a_set.remove(21)
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-136-e1324b18ad7c> in <module>() ----> 1 a_set.remove(21) KeyError: 21
リストのように、集合はpop()メソッドを持っている。
pop()メソッドは1つの値を取り除いてその値を返す。 ただし、集合の要素は順序付けされていないので、集合には「最後の」値というものはなく、したがって、どの値が取り除かれるのかを制御する方法はない。 どれが取り除かれるかは完全に不定だ。
a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}
a_set.pop()
1
a_set.pop()
3
a_set.pop()
36
a_set
{6, 10, 15, 21, 28, 45}
clear()
メソッドはすべての値を集合から削除し、空集合になる。
a_set.clear()
a_set
set()
空の集合からpopしようとすると、KeyError例外が出される。
a_set.pop()
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-142-e21c77f61fc4> in <module>() ----> 1 a_set.pop() KeyError: 'pop from an empty set'
Pythonのsetはいくつかの一般的な集合演算をサポートしている。
ある値が集合に含まれているかを確認するには、in演算子を使えばよい。これはリストの場合と同様に機能する。
a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
30 in a_set
True
31 in a_set
False
union()
メソッドは、どちらかの集合に含まれるすべての要素を含んだ新しい集合を返す。(和集合)
b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
a_set.union(b_set)
{1, 2, 3, 4, 5, 6, 8, 9, 12, 15, 17, 18, 21, 30, 51, 76, 127, 195}
intersection()
メソッドは、両方の集合に含まれるすべての要素を含んだ新しい集合を返す。(積集合)
a_set.intersection(b_set)
{2, 5, 9, 12, 21}
difference()
メソッドは、a_setには含まれるがb_setには含まれていないすべての要素を含んだ新しい集合を返す。(差集合)
a_set.difference(b_set)
{4, 30, 51, 76, 127, 195}
symmetric_difference()
メソッドは、どちらか一方だけの集合に含まれるすべての要素を含んだ新しい集合を返す。(対称差)
a_set.symmetric_difference(b_set)
{1, 3, 4, 6, 8, 15, 17, 18, 30, 51, 76, 127, 195}
以上のメソッドのうち、3つは対称的。
b_setからa_setの対称差 (symmetric difference) は、a_setからb_setの対称差。
b_set.symmetric_difference(a_set)
{1, 3, 4, 6, 8, 15, 17, 18, 30, 51, 76, 127, 195}
b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set)
True
2つの集合の和集合 (union) も対称的。
b_set.union(a_set) == a_set.union(b_set)
True
2つの集合の積集合 (intersection) も対称的。
b_set.intersection(a_set) == a_set.intersection(b_set)
True
2つの集合の差 (difference) は対称的ではない。
b_set.difference(a_set) == a_set.difference(b_set)
False
集合に尋ねることのできる事柄。
a_setはb_setの部分集合 (subset) 。 つまり a_set のすべての要素は set にも含まれている。
a_set = {1, 2, 3}
b_set = {1, 2, 3, 4}
a_set.issubset(b_set)
True
逆の言い方をすると、a_setのすべての要素はb_setの要素でもあるので、 「b_setはa_setの上位集合 (superset)」。
b_set.issuperset(a_set)
True
b_set に含まれていない値をa_setに追加すると、たちまち両方の結果はFalseになる。
a_set.add(5)
a_set.issubset(b_set)
False
b_set.issuperset(a_set)
False
ブール値のコンテクストでは、空の集合は偽。
is_it_true(set())
no, it's false
要素を1つでも持つ集合は真。
is_it_true({'a'})
yes, it's true
is_it_true({False})
yes, it's true
辞書は、「キーと値のペアからなる順序付けされていない集合」。
辞書にキーを追加するときは、そのキーに対応する値も同時に追加しなければならない(この値はあとでいつでも変更できる)。
Pythonの辞書は、既知のキーをもとに値を取得するのは効率的に行えるようになっているが、その逆方向はそうなっていない。
構文は集合に似ているが、値の代わりにキーと値のペアが必要になる。辞書を作ったあとは、キーを指定することで値を取り出せる。
各々の要素はキーと値のペアであり、要素の集合の全体は波括弧「{}」に包まれている。
a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'}
a_dict
{'database': 'mysql', 'server': 'db.diveintopython3.org'}
'server'はキーだ。このキーに関連づけられた値はa_dict['server']によって参照でき、その値は'db.diveintopython3.org'。
a_dict['server']
'db.diveintopython3.org'
a_dict['database']
'mysql'
値はキーによって取得できるが、キーを値によって取得することはできない。 つまり、a_dict['server']は'db.diveintopython3.org'になるが、'db.diveintopython3.org'はキーではないので、a_dict['db.diveintopython3.org']は例外を出す。
a_dict['db.diveintopython3.org']
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-164-15da1c9e76d5> in <module>() ----> 1 a_dict['db.diveintopython3.org'] KeyError: 'db.diveintopython3.org'
辞書には、事前に定められた上限サイズというものは一切ない。新しいキーと値のペアをいつでも辞書に追加できるし、既在のキーに対応する値もいつでも変更可能。
a_dict
{'database': 'mysql', 'server': 'db.diveintopython3.org'}
辞書に重複したキーを持たせることはできない。既存のキーに値を代入すると、古い値が追い出される。
a_dict['database'] = 'blog'
a_dict
{'database': 'blog', 'server': 'db.diveintopython3.org'}
キーと値のペアはいつでも追加できる。 この構文は既存の値を変更するときとまったく同じ。
a_dict['user'] = 'mark'
a_dict
{'database': 'blog', 'server': 'db.diveintopython3.org', 'user': 'mark'}
a_dict['user'] = 'dora'
a_dict
{'database': 'blog', 'server': 'db.diveintopython3.org', 'user': 'dora'}
辞書のキーについては大文字と小文字が区別されるので、この文は新たなキーと値のペアを作り、既存の値は書き換えない。
a_dict['User'] = 'mark'
a_dict
{'User': 'mark', 'database': 'blog', 'server': 'db.diveintopython3.org', 'user': 'dora'}
辞書は文字列しか扱えないわけではない。 辞書の値はどんなデータ型でもよく、 例えば、整数型、ブール値、任意のオブジェクトを使うことができるし、他の辞書を値にすることもできる。
また1つの辞書において、全ての値が同じ型である必要はなく、必要に応じて様々な型を混ぜて使うことができる。 辞書のキーとして使える型は値よりも制限されているが、文字列や数値、その他いくつかの型を使うことができる。 辞書のキーも、一つの辞書の中で様々なデータ型を混ぜて使うことができる。
リストや集合と同じように、len()関数は辞書に含まれるキーの数を教えてくれる。
SUFFIXES = {
1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
}
len(SUFFIXES)
2
リストや集合と同様に、特定のキーが辞書に含まれているかどうかを調べるには、in演算子が使える。
1000 in SUFFIXES
True
1000は辞書SUFFIXESのキーであり、 対応する値は8つの要素(正確には8つの文字列)を持つリスト。
SUFFIXES[1000]
['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
SUFFIXES[1024]
['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
SUFFIXES[1000]はリストなので、このリストの個々の要素を0から始まるインデックスで指定できる。
SUFFIXES[1000][3]
'TB'
辞書はif文のようなブール値のコンテクストで使うことができる。
ブール値のコンテクストでは、空の辞書は偽.
is_it_true({})
no, it's false
キーと値のペアを1つでも持っている辞書は真。
is_it_true({'a': 1})
yes, it's true
NoneはPythonの特別な定数で、これはnull値(無効値)である。 NoneはFalseではないし、0でもないし、空の文字列でもない。NoneをNone以外の値と比較すると、常にFalseが返る。
Noneは唯一のnull値であり、Noneは自身のデータ型 (NoneType) を持っている。Noneは任意の変数へ代入できるが、他のNoneTypeのオブジェクトを作ることはできない。Noneを値として持つすべての変数は互いに等しい。
type(None)
NoneType
None == False
False
None == 0
False
None == ''
False
None == None
True
x = None
x == None
True
y = None
x == y
True
ブール値のコンテクストでは、
is_it_true(None)
no, it's false
is_it_true(not None)
yes, it's true