はじめに
どうも、水無月せきなです。
Pythonの学習のために読んだチュートリアルについてのメモ書きです。
Pythonの環境構築に関しては、下記の記事を参考にDockerで構築しました。
チュートリアル
1. やる気を高めよう
内容は省略します。
2. Python インタプリタを使う
- Pythonの環境を整えたら、下記のコマンドでインタプリタを起動できる
python3.13
-
インタプリタの終了
>>>
が出ている状態でCtrl+D(Unix。WindowsはCtrl+z)、もしくはquit()
-
デフォルトだと、PythonのソースコードはUTF-8でエンコードされていると解釈される。ただ、標準ライブラリの識別子(メソッド・変数名等?)はASCIIであり、その他のポータブルなコードもその慣習に従うべき
3. 形式ばらない Python の紹介
コメント
- コメントの頭は
#
演算関係
-
/
(除算演算子)の戻り値は必ず浮動小数点。整数での商が欲しい場合は//
、剰余は%
- 浮動小数点と整数の変数が混ざっている場合の演算は、整数を浮動小数点に変えて行われる
文字列関係
- 文字列は「`」か「"」でくくる。「`」でくくった文字列の中で「"」を使う場合はエスケープが要らず、「`」はエスケープが必要(逆も同様)
- 「\」に続く文字をエスケープ処理してほしくない場合は、引用符の前に
r
を付ける(raw string) - 複数行の文字列
- 三連引用符 ("""...""" や '''...''')
- 末尾の改行は自動反映。行末に
\
を付けることで改行させないこともできる
- 文字列の連結
+
- 連続して並ぶ文字列
-
()
で囲まれた複数行の文字列 - 変数同士・変数と文字列の結合は
+
のみ
# 'un' を3回繰り返し、その後に 'ium'
3 * 'un' + 'ium'
> 'unununium'
'Py' 'thon'
> 'Python'
('複数の文字列を丸括弧で囲むと'
'連結される。')
> '複数の文字列を丸括弧で囲むと連結される。'
- 文字の取得
- 文字列は添え字で文字を取得可能
- Char型は無く、すべて文字列扱い
- インデックスに負の数を指定した場合は末尾から数える
- 部分文字列の取得はスライスで行う
- 文字取得時のインデックスで範囲外を指定するとエラーになるが、スライスはエラーにならずよしなに対応する
word[0:2] # 0番目(含む)から2番目(含めない)までの文字
word[2:5] # 2番目(含む)から5番目(含めない)までの文字
リスト
- リストは
[]
で表現 - 文字列と同様にインデックスとスライスが可能
- 連結は
+
-
list.append()
で要素を追加 - 変数へのリストの単純代入はコピーを作らない。なので、変更を加えると他の変数に影響が出る
rgb = ["Red", "Green", "Blue"]
rgba = rgb
id(rgb) == id(rgba) # 同じオブジェクトを参照している
>True
rgba.append("Alph")
rgb
> ["Red", "Green", "Blue", "Alph"]
- リストの長さは
len()
で取得 - リストの入れ子も可能(ジャグ配列的な)
スライス
- スライスのインデックスの初期値
- 最初のインデックス:0
- 二番目:対象のサイズ
- スライスで指定する範囲はインデックスの開始値を含み、終了値は含まない
- 文字列の長さの取得は
len()
- スライスは新しいリストを返す
- スライスには代入ができるので、サイズの変更や削除が可能
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters
> ['a', 'b', 'c', 'd', 'e', 'f', 'g']
# 一部の値を置き換える
letters[2:5] = ['C', 'D', 'E']
letters
> ['a', 'b', 'C', 'D', 'E', 'f', 'g']
# 一部の値を削除する
letters[2:5] = []
letters
> ['a', 'b', 'f', 'g']
# 要素全体を空のリストに置き換えてリストをクリアする
letters[:] = []
letters
> []
複数同時の代入 (multiple assignment)
代入文では、まず右辺の式がすべて評価され、次に代入が行われます。右辺の式は、左から右へと順番に評価されます。
→実は、タプルのパックとアンパックを組み合わせたものらしい
# こういうの
a, b = 0, 1
print
関数のあれこれ
- 文字列は引用符無しで出力・要素の間に空白を挿入
- キーワード引数 end で出力の末尾の制御が可能
>>> i = 256*256
>>> print('The value of i is', i)
The value of i is 65536
>>> a, b = 0, 1
>>> while a < 1000:
... print(a, end=',')
... a, b = b, a+b
...
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,
4. その他の制御フローツール
if文
if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0:
print('Zero')
elif x == 1:
print('Single')
else:
print('More')
for文
シーケンス型(リストもしくは文字列とか)の要素を順番に処理する
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
数値の順番で処理をする時はrnge()が使える
>>> for i in range(5):
... print(i)
...
0
1
2
3
4
break文
一番内側のforもしくはwhileから脱出
continue文
ループの次のイテレーションを実行
ループのelse節
breakやreturn・例外発生時を除いて、ループが終了すると実行される。
try ~ except
におけるelse
と類似。
pass
何もしない。最小のクラスの作成や関数実装中などに仮の処理を書くのに使える
match文
いわゆるswitch
。
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
関数の定義(def)
docstringについて
関数の本体の記述する文の最初の行は文字列リテラルにすることもできます。その場合、この文字列は関数のドキュメンテーション文字列 (documentation string)、または docstring と呼ばれます。
- 最初の行に目的を完結にまとめる
- 最初の行は大文字で初めて、ピリオドで終わらせる(英文想定?)
- さらにドキュメントを書く場合は、一行開けてそれ以降に記述する
値の戻し方
- returnで値を戻せる。未指定の場合は
None
が返る
引数
- 関数の引数にデフォルト値を指定することが可能
- 位置引数・キーワード引数で呼び出しが可能
-
*name
で仮引数を超えた位置引数のタプルを、**name
でそれを超えたキーワード引数の辞書を受け取れる - 位置引数で受け取るか、キーワード引数で受け取るかを関数側で指定できる
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| 位置またはキーワード |
| - キーワード専用
-- 位置専用
チュートリアル曰く、
もし引数の名前をユーザーに知らせる必要がないなら、位置専用引数を使用しましょう。これは引数の名前がユーザーにとって意味がなく、関数が呼ばれたときの引数の順序が問題であり、または、位置引数と任意のキーワードを使用する必要がある場合に便利です。
引数の名前に意味があり、それにより関数の定義がより明らかになる、または、ユーザーが引数の順番に縛られることを避けたほうがいいと考えるのなら、キーワード専用引数を使用しましょう。
APIの場合、将来引数の名前が変更された場合にAPIの変更ができなくなることを防ぐために、位置専用引数を使用しましょう。
とのこと。
引数でリストや辞書型を渡す時の展開(アンパック)
- リスト:引数の前に
*
を付ける - 辞書型:引数の前に
*
を付ける
関数のアノテーション
- 引数や戻り値の型を表すオプションのメタデータ
- 引数の場合は名前の後に
:
を挟んで型名、戻り値は引数と定義末端の:
の間に->
を書いてその後ろに記述する
def f(ham: str, eggs: str = 'eggs') -> str:
5. データ構造
リスト内包表記
- シーケンスを処理した結果やある条件に基づいて新たなリストを作る際に使用できる記法
squares = [x**2 for x in range(10)]
del文
- リストから要素を削除したり、スライス・変数の削除が行える
タプル
- リストなどと同じシーケンス型
- ただし、変更不能な不変型で、複数の型の要素で構成されることがほとんど(リストとは対照的)
# タプルの作成
t = 1, 2, "string"
# タプルの入れ子
u = t, (1, 2)
# u
# ((1, 2, "string"), (1, 2))
# 空のタプル
v = ()
# 要素が一個だけのタプル
w = 1,
# タプルのアンパック
# 左辺の数とタプルの要素数が一致している必要がある
x, y,z = t
集合型
- 重複する要素を持たず、順序付けられてもいない要素の集まり
- 中括弧でくくって作成する(作成時に重複があれば削除される)
- 空の集合型を作る場合は、必ず
set()
で作る必要がある({}だと空の辞書型ができる) - リストと同様に内包表記が可能
辞書型
- 一般的な辞書型
- delでキーと値のペアを削除できる
- キーの存在チェックは
in
キーワードで行う - リスト型と同様に内包表記が可能
条件に使う演算子について
- 優先順位
- 数値演算子(
+
など)> 比較演算子(>
など)> ブール演算子(and
など)
- 数値演算子(
- 比較演算子は連結可能
-
a < b == c
はa
がb
より小さく、なおかつb
がc
と等しいか
-
- ブール演算子について
- 短絡評価
- ブール演算子で評した結果を変数に入れると、最後に評価された値が入る
result = "hello" or "world" or ""
print(result)
# "hello"
6. モジュール
モジュールのインポート
# オーソドックスなインポート
import sample
# モジュール名.~でアクセスする
sample.hello()
# モジュール自体はインポートせず、その内部のものをインポートする
from sample import hello, test
# モジュール名は名前空間に無いので、直接呼出し
hello()
# モジュール内で定義されているすべてのもの(`_`始まりを除く)を直接インポートする
from sample import *
- asを付けることで使用時の名前を変えられる
import sample as sam
sam.hello()
-
python module.py <arguments>
の形で実行すると__name__
に__main__
が入るため、スクリプトとして実行される時のみの処理は次のように書ける
if __name__ == "__main__":
import sys
hello(sys.argv[1])
パッケージ
- モジュールの名前空間を
A.B
のような形で構造化するための方法 - ディレクトリをパッケージとして扱う場合は
__ini__.py
が必要 -
__ini__.py
では初期化処理もできる(__all__
を書いてfrom package import *
においてインポートされるモジュールのリストを書くことも可能)
# ケース1
import A.B.C
# トップのモジュールからフルで書く
A.B.C.hello()
# ケース2
from A.B import C
# インポートしたモジュール名からでOK
C.hello()
# ケース3
from A.B.C import hello
# インポートした関数・変数名のみでOK
hello()
7. 入力と出力
- 文字列の書式指定
- str.format()の書式指定と同様の指定は
f''
でもできるっぽい
# フォーマット済み文字列リテラル
year = 2025
text = 'This'
f'{text} year is {year}.'
# 'This year is 2025.'
# str.format()を使用
yes = 1_000
total = 1_100
percentage = yes / total
'{:-5} YES {:2.2%}'.format(yes, percentage)
# ' 1000 YES 90.91%'
ファイルの読み書き
- ファイルを開くには
open()
を使う -
open()
で開く時は一緒にwith
を使うか、close()
を呼び出す必要がある - エンコードのデフォルトはプラットフォーム依存
- 改行コードは読み込み時に
\n
へ変換され、書き込み時はプラットフォーム依存の改行コードで書き込まれる -
mode
の引数でファイルを開く際のモードを指定できる
open(filename, mode, encoding=None)
mode の値 |
意味 |
---|---|
r |
読み取り専用 |
w |
書き込み専用(既存は上書き) |
a |
追記 |
r+ |
読み書き両用 |
※上記以外にもあり
Jsonのシリアライズとデシリアライズ
-
json
モジュールを使用して可能
import json
# シリアライズ
x = [1, 'simple', 'list']
json.dumps(x)
# デシリアライズ
# fはファイルオブジェクト
x = json.load(f)
8. エラーと例外
例外処理
-
try ~ except ~ finally
で行う - 複数の
except
を置くことができ、一つのexcept
にタプルで複数の例外を紐づけることができる -
as
で例外を変数として扱い、.args
で例外の引数を参照できる -
else
節内に書いたコードは、try
で例外が起きなかった場合に実行される - 例外の送出は
raise
で行う - 未処理の例外は処理済みの例外のエラーメッセージに含まれる
-
raise
のfrom
オプションを使うことで、例外の変換や例外情報の連鎖を止めたりできる
try:
raise NameError('Error!')
except NameError as ne:
print(ne)
except Somerror as se:
# キャッチした例外から例外を生成
raise CustomError from se
else:
# 例外の連鎖を無効化
raise RuntimeError from None
finally:
print('finally')
9. クラス
- 通常のクラスメンバはPublic扱い
- プライベートな変数は無いが、
_
で始まるメンバは慣習的に非Publicとみなされる - メソッドの宣言で第一引数にクラス自身を定義する必要がある
- 多重継承が可能
- 変数の参照は基本的にローカルスコープ。
nonlocal
を付けると外側のスコープにも存在し、global
を付けるとモジュールのグローバルスコープにも存在することになる
# クラス定義
class Sample:
# 処理を書く
# インスタンス化
s = Sample()
# 派生クラスの定義
class Chaild(Sample):
# 処理を書く
- いわゆるコンストラクタのようなものは
__init__
で実装する
# シンプルな例
def __init__(self)
selef.initialized = True
# 引数を持つパターン
def __init__(self, initialized)
selef.initialized = initialized
イテレータ
-
__next__()
メソッドを持つオブジェクトを返す__iter__()
を定義することで、イテレータの自作が可能 - ジェネレータを使用しての作成も可能
10. 標準ライブラリミニツアー
標準ライブラリに関する簡単な紹介。
内容は省略します。
11. 標準ライブラリミニツアー --- その 2
標準ライブラリに関する簡単な紹介。
内容は省略します。
12. 仮想環境とパッケージ
venv
とpip
の説明。
内容は省略します。
参考文献