【Python】『独学プログラマー』再読メモ
LLM経由で久しぶりにPythonコード触りはじめたけど基礎がすっかり抜け落ちてしまいエラー解決とかで時間かかってしまってたので再読。(初読18年5月なので5年半ぶり)
『独学プログラマー Python言語の基本から仕事のやり方まで』/ 2018/2/24
仕様
インデント
インデントはPythonにコードブロック(コードの塊)の開始と終了を伝えるために使います。これから出てくるコード例にインデントがあったら、1段のインデントにスペースを4つ使っている
データ型
Pythonにおいてオブジェクトというのは、同一性、データ型、値、という3つの要素がある
型の明示宣言
Python は動的型付け言語のため、明示的に型を書かなくても動作する
型宣言: Pythonでは型を明示的に宣言しないので、int x;を削除しました。
変数ルール
1.変数名にはスペース(空白文字)を含められません。もし2つの単語を1つの変数名に含めたければ、アンダースコア( _ )を単語の間に置くと良いでしょう。 例:my_variable = "A string!"
2.変数名には文字、数値、アンダースコア記号、の3種類の文字だけを含められます。
3.変数名の1文字目に数字は使えません。しかし1文字目にアンダースコアは使えます。アンダースコアで始まる変数名には特別な意味があります。後ほどその意味を紹介するので、それまでは使わないようにしましょう。
4.Pythonのキーワードは変数名に使えません。キーワードの一覧は以下にあります。 https://docs.python.org/ja/3/reference/lexical_analysis.html#keywords
エラー区分
- 構文エラー(Syntax Error)
- 例外(Exeception)
- 構文ではないエラーはすべて例外
- ZeroDivisionError
- ゼロで割り算したときのエラー
- ZeroDivisionError
- 構文ではないエラーはすべて例外
算術演算子
比較演算子
論理演算子
関数 function
関数の基本フォーマット
def 関数名 (引数):
関数定義
def f(x):
return x * 2
def=define 定義
関数名には大文字を使わずにlike_this的なアンダースコアで区切ることが推奨される
組み込み関数の例
Pythonにデフォルトで用意されている関数
len("hello") # 文字数 / オブジェクトの長さを出力
str(100) # 整数を文字列に変化
int("1") # 文字列を整数に変化
float(100) # オブジェクトから浮動小数点オブジェクトを返す
input関数
プログラムを動作させている人が値を入力できる組み込み関数
age = input("Enter your age:")
int_age = int(age)
if int_age < 21:
print("20歳以下です")
else:
print("21歳以上です")
引数
オプション引数
引数の入力を必須にしないことが可能。
その場合の後工程の処理のためにデフォルトの引数をあらかじめインプットしておく方法。
関数名(引数名 = 引数値)
def f(x=2):
return x ** x
print(f())
print(f(4))
変数のスコープ
どこで変数を宣言しているかでスコープが変わる
- グローバルスコープ / 変数
- 関数の外で定義した場合
- ローカルスコープからグローバル変数を書き込む場合はglobalキーワードを使って明示的に変更する
- ローカルスコープ / 変数
- 関数内で宣言した場合
関数内からグローバル変数を変更する例
x = 100
def f():
grobal x
x += 1
print(x)
f()
例外処理
try: 発生する可能性がある例外エラーが含まれる
except: 例外が発生した場合にのみ実行されるコードを記載
try:
a = input("type a number:")
b = input("type another:")
a = int(a)
b = int(b)
print(a / b)
except(ZeroDivisionError, ValueError):
print("Invalid input")
ドキュメンテーション文字列
引数が特定のデータ型でないと正しく動作しない関数を作った場合、呼び出す人に引数データ型を伝えるための文字列。
def add(x, y):
"""
Return x + y.
:pram x: int.
:pram y: int.
:return: int sum of x and y.
"""
return x + y
コンテナ
- コンテナの種類
メソッド
関数に似た概念だが、メソッドは特定のデータ型に密接に紐づけられている関数。
メソッドはオブジェクトに紐づけて呼び出す。
"Hello".upper()
"Hello".replace("o", "@")
リスト list
リスト:好きな順番でオブジェクトを格納しておけるコンテナ
# 宣言方法①
fruit = list()
# 宣言方法②
fruit = []
# 格納方法
fruit = ["Apple", "Orange", "Pear"]
print(fruit)
# 新しいオブジェクトの追加 .append
fruit.append("Banana")
print(fruit)
# インデックスでの呼び出し
print(fruit[0])
print(fruit[2])
# インデックス番号で要素を書き換えするケース
fruit[3] = "Banana2"
print(fruit[3])
print("fruit:", fruit)
# pop:リスト末尾から要素を取り除くもの
removed_item = fruit.pop() # 取り除いた要素を別の変数に保存
print("Removed item:", removed_item) # 取り除いた要素を表示
print(fruit) # リストの状態を表示
タプル tuple
リストとは異なりイミュータブル(変更不可能)なもの
一度作成したら要素の追加も更新も不可能
# 宣言方法①
my_tuple = tuple()
# 宣言方法②
my_tuple = ()
# 格納例
rndm = ("M. Jackson", 1958, True)
print(rndm)
# in 特定の要素が入っているかの確認
print("1958" in rndm)
print(1958 in rndm)
辞書 dict
- 2つのオブジェクトを関連付けて保存するコンテナ
- キーバリュー形式でマッピングして保持しておける
- ミュータブルなコンテナ
# 宣言①
my_dict = dict()
# 宣言②
my_dict = {}
# 格納例
fruits = {"001": "Apple", "002": "Banana"}
print(fruits)
# バリューの追加
fruits["003"] = "Orange"
# キーで参照
print(fruits["003"])
# in 要素チェック
"003" in fruits
コンテナの中にコンテナを格納
blists = []
slists1 = ["s1-1", "s1-2", "s1-3"]
slists2 = ["s2-1", "s2-2", "s2-3"]
slists3 = ["s3-1", "s3-2", "s3-3"]
blists.append(slists1)
blists.append(slists2)
blists.append(slists3)
print(blists)
[['s1-1', 's1-2', 's1-3'], ['s2-1', 's2-2', 's2-3'], ['s3-1', 's3-2', 's3-3']]
文字列操作
複数行の文字列:三重クォート
"""line one
line two
line three
"""
文字列数式
"cat" + "in" + "hat"
"Sawer" * 3
大文字小文字変換 upper / lower
print("We held three truths...".upper())
print("WE HELD THREE TRUTHS...".lower())
書式化 format
formatを使うと文字列の一部後から穴埋めできる(複数要素も可能)
name = input("Enter your name")
age = input("Enter your age")
print("こんにちは、{}さん。あなたは{}歳ですね。".format(name, age))
結合 join
すべての文字列の間に新しい文字列の追加が可能
text = "abcdefg"
print("/".join(text))
空白除去 strip
s = " fan "
print(s.strip())
置換 replace
text = "xxxxxxxx"
print(text.replace("x","y"))
文字列検索 index
print("animals".index("m"))
エスケープ文字 \
print("彼女は\"そうだね\"といった")
※ Macでのバックスペース入力はOption+¥マーク
改行 \n
print("apple\norange\nbanana")
スライス [:]
list = ["a", "b", "c", "d", "e"]
print(list[0:2])
ループ処理
for構文
for 変数名 in イテラブル
コードブロック
イテラブル:繰り返し可能なオブジェクト
name = "Tester"
for character in name:
print(character)
lists = ["list1", "list2", "list3"]
for list in lists:
print(list)
要素のインデックス値を用意する例
list = ["aaa", "bbb", "ccc", "ddd"]
for i, new in enumerate(list):
new = list[i]
new = new.upper()
list[i] = new
print(list)
- enumerate関数
- イテラブルなものをループ処理させる際に要素のインデックス値を取得できる関数
range
組み込み関数rangeは整数を順番に生成可能
for i in range(1, 10):
print(i)
whileループ
式がTrueに評価されてる間はループを繰り返す
x = 10
while x > 0:
print('{}'.format(x))
x -= 1
print("Hello!World")
break
break文に達するとすぐにループ終了が可能
for i in range(0, 100):
print(i)
break
continue
実行中の反復処理を途中で終了して次の反復処理を実行させる
for i in range(1, 5):
if i == 2:
continue
if i == 4:
continue
print(i)
入れ子ループ
for i in range(1, 3):
print(i)
for letter in ["a", "b", "c"]:
print (letter)
モジュール
- 大きなファイルを複数に分割しておく
- そのファイルそれぞれをモジュールと呼ぶ
- .py拡張子付きのものをモジュールとする
- 組み込みモジュールも存在する
import[モジュール名]
import math
import random
print(math.pow(2, 3)) # xのy乗 計算
print(random.randint(0, 99))
モジュール内のテストコード
if __name__ == "__main__":
print("hello!")
直接ファイルを実行したときはprintされるが、モジュールとして呼び出ししたときは呼び出されないようになる
ファイル
ファイルに書き出す open
- Open関数は2つの引数が必要
- 1:開こうとしているファイルのパス
- 2:どんなモードでファイルを開きたいのか
- r 読み込み専用
- w 書き出し専用
- w+ 読み書き両方
- オプション:変換コード utf等
st = open("st.txt", "w", encoding="utf-8")
st.write("Hi from Python!")
st.close()
ファイルを自動的に閉じるためのwith
with open("st.txt", "w") as f:
f.write("Hi")
コードが実行されたあと自動的に閉じられる
プログラミングパラダイム
関数型プログラミング
- 関数型プログラミングの起源はラムダ計算
- グローバルステートを排除することで手続き型プログラミングの問題を解消した
- グローバルステートに依存せず、関数によって渡された引数によってのみ変わる
- 関数の戻り値は通常、他の関数に引数として渡される
- グローバルステートに依存しないことで副作用をなくす
オブジェクト指向プログラミング
- 関数型プログラミングのように引数に状態を渡すのではなく、オブジェクトに対して状態をもたせる
- 複数のクラスで相互に作用するオブジェクトの集合を定義する
- すべてのオブジェクトはクラスのインスタンス
Pythonにおけるクラス例
class クラス名:
スイート
- クラスのスイート部分には単純文 or メソッドと呼ばれる複数文を書く
- メソッドは関数に似ているがクラスの内部で定義し、そのクラスから生成したオブジェクトを通してのみ呼び出せる
- メソッド名はすべて小文字でアンダーバーで区切る
class Orange:
def __init__(self):
print("Created")
- self変数はインスタンス変数の定義に使う
- 通常インスタンス変数は__init__という特別なメソッドの中で定義する
class Orange:
def __init__(self, w, c):
self.weight = w
self.color = c
print("Created")
orange1 = Orange(10, "dark orange")
print(orange1)
新しいオブジェクトを作ることをクラスのインスタンス化という
オブジェクト指向プログラミングの4代要素
- カプセル化
- 抽象化
- ポリモーフィズム
- 継承
カプセル化
- オブジェクトによって複数の変数(状態ステートを保持します)とメソッド(状態を変更したり状態を使用して計算したりします)をまとめること
- データをクラス内に隠蔽して外から見えないようにすること
- Pythonにプライベート変数は存在しない。
- clientからアクセスしてほしくない変数やメソッドには名前の前に_をつける
抽象化
- 対象から小さな特徴を除いて本質的な特徴を集めた状況にすること
継承
- クラスを作るときに他のクラスからメソッドや変数を受け継ぐこと
- 子クラスの変更は親には影響しない
- 子クラスが親クラスのメソッドを別の実装で書き換えることをメソッドオーバーライドという
class Shape:
def __init__(self, w, l):
self.width = w
self.length = l
def print_size(self):
print("{} by {}".format(self.width, self.length))
class Square(Shape):
def area(self):
return self.width * self.length
a_square = Square(20, 20)
print(a_square.area())
コンポジション
- 「has-a 関係」を表し、別クラスのオブジェクトを変数としてもたせる
- 犬とその飼主という関係を表すのにコンポジションを使い、犬は1人の飼い主を持つ、と表現する
class Dog:
def __init__(self, name, breed, owner):
self.name = name
self.breed = breed
self.owner = owner
class Person:
def __init__(self, name):
self.name = name
mick = Person("Mick Jagger")
stan = Dog("Sanley", "Bulldog", mick)
print(stan.owner.name)
クラス変数とインスタンス変数
- すべてのオブジェクトはクラスのインスタンス
- インスタンスはクラスから作られる
- Pythonではクラス自体もオブジェクト
- Smarlltalkに由来している
- Pythonのどのクラスもオブジェクトでtypeクラスのインスタンス
- typeクラスから作られるオブジェクトを「クラスを作るクラス」というニュアンスでメタクラスとする
インスタンス変数
self.変数 = 値
インスタンス変数はインスタンスオブジェクトに属する
クラス変数
- クラス変数は、クラス定義の中に通常変数のように定義される
- クラスオブジェクトから参照できるしインスタンスオブジェクトからも参照できる
- クラス変数が便利なのは、そのクラスから作られたインスタンスオブジェクトのどこからでも利用できること
Discussion