Pythonのキホン - 変数編
はじめに
Pythonを使い始めて数年、ある程度アウトプットしていきたいことも溜まってきたので、自分の振り返りも兼ねて記事にしました。
本記事はPython使い始めて〜1年くらいの人をターゲットにしております。
正直こんなことはわかるよ!とかもあるかと思いますが、温かい目で見ていただけると幸いです。
ここではPython3のお話をメインに記載していきます。
PEPについて
大体Pythonで開発を行う場合に目を通すのが、PEP8のドキュメントかと思います。
PEPとは「Python Enhancement Proposal」の略で、コーディング規約、ドキュメント規約など、Pythonの機能拡充について議論したものを文書化したものとなります。
前述したPEP8はコーディング規約となっており、他にはPEP257や、PEP484など様々なものが文書化されています。
Pythonで定義されているコーディングスタイルは様々で他にもflake8, Google Python Style Guide, Pylintなどありますが、PEPにまず目を通しておくことで他のスタイルガイドを適用したプロジェクトでもある程度臨機応変に立ち回れるようになりますので、開発を行う際は目を通しておくことをお勧めします。
- 参考サイト - PEP
変数
変数については代入、スコープ、型など項目別に分けて記載いたします。
入門向けのものもありますがパラパラとお読みいただけると幸いです。
定義・代入について
変数の定義は下記のような形で宣言できます。
# 定義
num = 10
text = "textだよ"
# 表示:10 textだよ
print(num, text)
# 代入
num = 11
text = "代入だよ"
# 表示:11 代入だよ
print(num, text)
複数定義する場合は、下記のように定義できます。
# 定義
num, text = 10, "textだよ"
# 表示:10 textだよ
print(num, text)
# 代入
num, text = 11, "代入だよ"
# 表示:11 代入だよ
print(num, text)
またこのような形でも定義できます。
# 定義
num1 = num2 = num3 = 10
# 10 10 10
print(num1, num2, num3)
※豆知識
インタラクティブなインタプリタ上で上記の定義上記の定義を行う際は整数キャッシュなるものが働くので、インタラクティブな環境上でミュータブルな変数として使用する場合は注意が必要です。
(なるべくイミュータブルな場合に利用するようにしましょう)
整数キャッシュはintの場合 -5 ~ 256 の範囲で効きます。
(この辺りを見るとわかるかと思います。)
他の型では特段意識しなくても大丈夫です。
# 定義
num1 = num2 = num3 = 257
# 表示:257 257 257
print(num1, num2, num3)
# 表示:4462199600 4462199600 4462199600
# ※環境によってidは異なります。
print(id(num1), id(num2), id(num3))
# 新しく別で変数を作成
num4 = 257
# オブジェクトに対する評価:False
num1 is num4
# 値に対しての評価:True
num1 == num4
値の入替について
代入において値を入れ替えたい場合は下記が有効です。
# 値の定義
text1 = "1です"
text2 = "2です"
# 表示:1です 2です
print(text1, text2)
# 入替
text1, text2 = text2, text1
# 表示:2です 1です
print(text1, text2)
スコープについて
グローバルな変数を使いたい場合は特段何もなければ下記のような形で使用可能です。
global_var = "globalな変数です"
def func(x):
print(global_var, x)
# 表示:globalな変数です 123
func("123")
スコープ内でグローバル変数を変更したい場合は、
スコープ内で下記のように宣言すると使用できます。
Pythonではグローバル変数が意図しない形で変更されないようにこのような宣言が必要になってきます。
global_var = "globalな変数です"
def func(x):
global global_var
global_var = "スコープ内で変更"
print(global_var, x)
# 表示:globalな変数です
print(global_var)
# 表示:スコープ内で変更 123
func("123")
またネストされたスコープ内で変数を使用したい場合 nonlocal を使うことで
使用が可能になります。
def func1():
x = 10
def func2():
nonlocal x
print(x)
x += 1
func2()
print(x)
# 表示:
# 10
# 11
foo()
グローバル変数をモジュール間で共有する
グローバル変数を異なるモジュール間で参照したい場面など多くあることでしょう。
その場合は下記のような形で定義すると良いです。
global_var = "グローバル変数だよ"
# グローバル変数のインポート
import config
def func1():
print("func1(): " + config.global_var)
# グローバル変数のインポート
import config
def func2():
print("func2(): " + config.global_var)
# モジュールのインポート
import func1, func2
# 表示:func1(): グローバル変数だよ
func1()
# 表示:func2(): グローバル変数だよ
func2()
型
Pythonでは様々な型がございます。
動的型付け言語なのでそこまで意識しなくても、、という人はいらっしゃるかと思いますが、
ある程度知っておくことで実装する際に動的型付け言語であるPythonでも
型安全を意識した作りはできるので、覚えておいて損はないと思います。
数値型
数値型には3種類あります。Python2ではintとlongが分かれていましたが、
Python3では統一されました。
-
数値型の範囲について
基本的にはsysモジュールを使って確認できます。
宣言した値によって動的に型が定義されます。型 内容 最大値・最小値 int 整数 上限なし(メモリが許す限り) float 浮動小数点数 sys.float_infoの範囲 complex 複素数 虚部と実部はsys.float_infoの範囲 -
数値型の演算について
mathモジュールを用いた演算等もありますが、
ここでは割愛して基本的な演算のみ載せます。演算 結果 備考 x + y x と y の和 - x - y x と y の差 - x * y x と y の積 - x / y x と y の商 - x // y x と y の商を切り下げたもの 結果は常に負の無限大の方向に丸められる。1//2の場合は0、 (-1)//2 は -1 、 1//(-2) は -1 、そして (-1)//(-2) は 0 となる。 x % y x / y の剰余 複素数型は不可 -x x の符号反転 - +x x そのまま - abs(x) x の絶対値 - int(x) x の整数への変換 float -> intへの変換はC言語と同様の丸め方, 数値リテラルは数字 0 から 9 または等価な Unicode のみ float(x) x の浮動小数点数への変換 floatは、文字列 "nan" と "inf" を、オプションの接頭辞 "+" または "-" と共に、非数 (Not a Number (NaN)) や正、負の無限大として定義。数値リテラルは数字 0 から 9 または等価な Unicode のみ complex(re, im) 実部 re, 虚部 im の複素数( im のデフォルトは 0 ) 数値リテラルは数字 0 から 9 または等価な Unicode のみ x.conjugate() 複素数 x の共役複素数 - divmod(x, y) (x // y, x % y) からなる返り値 複素数型は不可 pow(x, y) x の y 乗 pow(0, 0) を 1 と定義 x ** y x の y 乗 0 ** 0 を 1 と定義 -
ビット単位演算について
ビット単位演算はint型でのみ利用ができます。演算 結果 備考 x y x と y の論理和(bit単位) x ^ y x と y の排他的論理和(bit単位) - x & y x と y の論理積(bit単位) - x << n x の n ビット左シフト 負の値は不可 x >> n x の n ビット右シフト 負の値は不可 ~x x のビット反転 -
シーケンス型
シーケンス型にはリスト、タプル、range、文字列型、バイナリシーケンス型の5種類あります。
ひとつずつ分解して見てみましょう。
- リスト型
宣言は下記のような形になります。
# 空のリスト
_list = [] # -> []
# あらかじめ定義
_list = [1] # -> [1]
_list = [1, 2] # -> [1, 2]
# リスト内包表記を使用
_list = [x for x in range(10)] # -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 型コンストラクタを使用
_list = list() # -> []
_list = list([1, 2]) # -> [1, 2]
_list = list([x for x in range(10)]) # -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
リスト型で使える関数にはsortがあります。(シーケンス型共通で使えるものは後述で確認できます。)
またsorted関数を使うことで新たにインスタンスを生成することもできます。
sort関数は破壊的メソッドなので使う際には気をつけましょう。
# 0 ~ 10 のリストを作成
_list = [x for x in range(10)] # -> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# リストを降順にする
_list.sort(reverse=True)
# リストを昇順にする
_list.sort()
sort関数では引数にkeyを指定することができます。
keyを使用した形でこのようなソートも可能です。
# 文字列 のリストを作成
_list = ["hoge", "ho", "hog"]
# リストを長さの短い順にソート
_list.sort(key=len)
- タプル型
タプルはイミュータブルなシーケンス型です。一度定義したら変更できません。
宣言は下記のような形になります。
# 空のタプル
_tuple = () # -> ()
# あらかじめ定義
_tuple = (1,) # -> (1,)
_tuple = (1, 2) # -> (1, 2)
# 型コンストラクタを使用
_tuple = tuple() # -> ()
_tuple = tuple([1, 2]) # -> (1, 2)
タプルはイミュータブルなので、要素の追加や削除はできません。
ただし、タプル内の要素がミュータブルなオブジェクト(例:リスト)の場合は、
その要素自体は変更可能です。
# タプル内にリストを含む場合
_tuple = ([1, 2], [3, 4])
# タプル内のリストは変更可能
_tuple[0].append(3) # -> ([1, 2, 3], [3, 4])
- range型
range型は数値のシーケンスを表すイミュータブルなシーケンス型です。
主にfor文などで使用されます。
# 0から4までのシーケンス
r = range(5) # -> range(0, 5)
# 2から5までのシーケンス
r = range(2, 6) # -> range(2, 6)
# 2から10まで2ずつ増加するシーケンス
r = range(2, 11, 2) # -> range(2, 11, 2)
- 文字列型
文字列型は文字のシーケンスを表すイミュータブルなシーケンス型です。
Python3では文字列はUnicodeで表現されます。
# 文字列の定義
s = "Hello" # -> "Hello"
s = 'World' # -> "World"
# 複数行の文字列
s = """Hello
World""" # -> "Hello\nWorld"
文字列には様々なメソッドが用意されています:
# 文字列の結合
s1 = "Hello"
s2 = "World"
s = s1 + " " + s2 # -> "Hello World"
# 文字列の分割
s = "Hello,World"
parts = s.split(",") # -> ["Hello", "World"]
# 文字列の置換
s = "Hello World"
s = s.replace("World", "Python") # -> "Hello Python"
# 大文字・小文字の変換
s = "Hello"
s_upper = s.upper() # -> "HELLO"
s_lower = s.lower() # -> "hello"
- バイナリシーケンス型
バイナリシーケンス型にはbytes型とbytearray型があります。
bytes型はイミュータブル、bytearray型はミュータブルです。
# bytes型の定義
b = b"Hello" # -> b"Hello"
b = bytes([72, 101, 108, 108, 111]) # -> b"Hello"
# bytearray型の定義
ba = bytearray(b"Hello") # -> bytearray(b"Hello")
ba = bytearray([72, 101, 108, 108, 111]) # -> bytearray(b"Hello")
シーケンス型共通の操作
シーケンス型には共通の操作がいくつかあります:
# 要素の取得
s = "Hello"
print(s[0]) # -> "H"
print(s[-1]) # -> "o"
# スライス
s = "Hello World"
print(s[0:5]) # -> "Hello"
print(s[6:]) # -> "World"
# 長さの取得
s = "Hello"
print(len(s)) # -> 5
# 要素の存在確認
s = "Hello"
print("H" in s) # -> True
print("x" in s) # -> False
# 連結
s1 = "Hello"
s2 = "World"
print(s1 + " " + s2) # -> "Hello World"
# 繰り返し
s = "Ha"
print(s * 3) # -> "HaHaHa"
セット型
セット型は重複のない要素のコレクションを表すミュータブルな型です。
要素の順序は保証されません。
# セットの定義
s = {1, 2, 3} # -> {1, 2, 3}
s = set([1, 2, 3]) # -> {1, 2, 3}
# 要素の追加
s.add(4) # -> {1, 2, 3, 4}
# 要素の削除
s.remove(4) # -> {1, 2, 3}
# 集合演算
s1 = {1, 2, 3}
s2 = {3, 4, 5}
print(s1 | s2) # 和集合 -> {1, 2, 3, 4, 5}
print(s1 & s2) # 積集合 -> {3}
print(s1 - s2) # 差集合 -> {1, 2}
print(s1 ^ s2) # 対称差 -> {1, 2, 4, 5}
辞書型
辞書型はキーと値のペアを格納するミュータブルな型です。
キーはイミュータブルな型である必要があります。
# 辞書の定義
d = {"key1": "value1", "key2": "value2"}
d = dict(key1="value1", key2="value2")
# 要素の追加・更新
d["key3"] = "value3"
d.update({"key4": "value4"})
# 要素の取得
value = d["key1"]
value = d.get("key1") # キーが存在しない場合Noneを返す
value = d.get("key1", "default") # キーが存在しない場合デフォルト値を返す
# 要素の削除
del d["key1"]
value = d.pop("key2") # 要素を削除して値を返す
# キーと値の取得
keys = d.keys()
values = d.values()
items = d.items()
おわりに
以上、Pythonの基本的な型とその操作方法について説明しました。
これらの型を適切に使い分けることで、より効率的で読みやすいコードを書くことができます。
また、型について理解を深めることで、バグの少ない堅牢なプログラムを作成することができます。
次回は、これらの型を使った制御構文(if文、for文、while文など)について説明する予定です。(次回は、暇ができたら。。)
Discussion