はじめに
この記事は、Pythonの自己学習で学んだこと(基礎的なこと)を書き留めておく覚え書きです。
環境構築手順や、アプリケーション作成のノウハウなどについては触れていませんので、あらかじめご了承ください。
実行環境
- MacOS 11.6.2
- Python 3.9.7
基礎編
変数
変数宣言
変数名を書くだけで使用できる。キーワードは不要。
x = 100 + 123
x.bit_length() # ビット数を取得
8
None
None
は、何もない状態を示す。Javaで言えばnull
のようなイメージ。
演算
除算結果の小数点以下を切り捨てる
20//3
6
べき乗
3**2
9
文字列の繰り返し
文字列型の値に対して乗算を行うと、その文字列を繰り返す。
msg1 = 'hello'
msg2 = '!'
print(msg1, msg2 * 10)
hello !!!!!!!!!!
フォーマット
文字列を変数で置き換える
format関数を使うと、文字列の{}
で囲んだ部分が変数に置き換わって返却される。
置き換える値はformat関数に渡した順で使用されるが、{1}
のように位置番号を指定すると順番を変更できる。
prices = [100, 250, 800]
'お買い上げ金額は{1}点で{0}円です。'.format(prices[0] + prices[1] + prices[2], len(prices))
'お買い上げ金額は3点で1150円です。'
書式を指定したフォーマット
# 本来ならば定数としたいが、Pythonには該当する仕組みがない
bmi = 22
height = float(input('身長を入力(cm) > ')) # ユーザーの入力を、float型に変換して代入
weight = bmi * (height / 100) ** 2
# endを指定することで改行を抑止できる
print('身長が{}cmの場合の標準体重は'.format(height), end = '')
# 小数点以下第2位まで表示する
print('{:.2f}kgです。'.format(weight))
身長を入力(cm) > 151
身長が151.0cmの場合の標準体重は50.16kgです。
書式化演算子
文字列の後の%
は、書式化演算子を意味する。ただし、format関数で代替可能。
name = input('汝の名は?> ')
print('%s よ、よく来たな。' % name)
汝の名は?> 勇者
勇者よ、よく来たな。
タプル
タプル型の定義
タプルは順序づけられた複数の値を格納するために使用し、一度設定した値は変更できない(immutable=不変)。
タプルは、カンマ区切りの値を丸括弧で囲むことで定義する。
a = (1,) # 1要素の場合、末尾にカンマが必要
b = (1,2,3)
print(a)
print(b)
(1,)
(1, 2, 3)
リスト
リストの定義
カンマ区切りの値を角括弧で囲むとリストが定義できる。タプルとは異なり、設定した値は後からでも変更可能。
a = [1, 2, 3]
print(a)
[1, 2, 3]
リストのコピー
元のリストの変更の影響を受けないようにするためには、単なる代入ではなくリストをコピーする。
下記の例では、リストa
の内容を変更しても、b
, c
, d
の内容は変わらないことが確認できる。
a = [1, 2, 3]
b = a.copy()
c = list(a)
d = a[:]
a[1] = 'hello'
print(a, b, c, d, sep='\n')
[1, 'hello', 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
初期化
range
関数の結果など、イテラブルなオブジェクトから、リストの初期値を設定できる。
numList = list(range(1, 6))
print(numList)
[1, 2, 3, 4, 5]
リスト内包表記
イテラブルなオブジェクトを評価した結果から、リストを生成できる。
list1 = [num for num in range(1, 6)] # そのままリスト化
list2 = [num -1 for num in range(1, 6)] # 取り出した値を減らす
list3 = [num for num in range(1, 6) if num % 2 == 1] # 条件を満たす値だけを追加
print(list1, list2, list3, sep='\n')
[1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]
[1, 3, 5]
zip関数による複数リストからの要素取り出し
zip関数を使うと、複数のリストから値のペアを作成できる(各要素はタプル型となる)。
# 2つのリストから値のペアを作る
eto = ['酉', '戌', '亥']
animal = ['とり', 'いぬ', 'いのしし']
list(zip(eto, animal))
[('酉', 'とり'), ('戌', 'いぬ'), ('亥', 'いのしし')]
3つのリストから組を生成する場合の例
year = ['H29', 'H30', 'H31']
eto = ['酉', '戌', '亥']
animal = ['とり', 'いぬ', 'いのしし']
# zip関数で、複数のシーケンス要素を集めたタプル型のイテレータを作成する
for year, eto, animal in zip(year, eto, animal):
print(year, ':', eto, '({})'.format(animal))
H29 : 酉 (とり)
H30 : 戌 (いぬ)
H31 : 亥 (いのしし)
辞書
辞書型の定義
カンマ区切りの値を波括弧で囲むと、辞書型の変数(連想配列)が定義できる。
dic = { 'key1': 'value1', 'key2': 'value2' }
print(dic['key2'])
value2
関数で辞書を作成する
dict
関数にリストを渡すと、リストの各要素を項目として持つ辞書を生成できる。
seq1 = dict([['a', 'b'], ['c', 'd'], ['e', 'f']])
seq2 = dict(['ab', 'cd', 'ef']) # 渡す文字が2文字以外だとエラーになる
seq3 = dict(('ab', 'cd', 'ef')) # タプルを渡しても結果は同じになる
print(seq1, seq2, seq3)
{'a': 'b', 'c': 'd', 'e': 'f'} {'a': 'b', 'c': 'd', 'e': 'f'} {'a': 'b', 'c': 'd', 'e': 'f'}
辞書型要素のイテレーションアクセス
for inで辞書の各要素に対して繰り返し処理ができる。
# 辞書の定義
spells = { 'ホイミ': 3, 'ルーラ': 8, 'ギラ': 2 }
# キーのみの取り出し
for key in spells:
print(key, sep=', ')
# 値のみの取り出し
for value in spells.values():
print(value, sep=', ')
# 要素の取り出し(各要素はタプルとなる)
for item in spells.items():
print(item)
ホイミ
ルーラ
ギラ
3
8
2
('ホイミ', 3)
('ルーラ', 8)
('ギラ', 2)
リスト内包表記
辞書でも、リスト内包表記を使って初期化を行うことができる。
eto = ['酉', '戌', '亥']
animal = ['とり', 'いぬ', 'いのしし']
# リスト内包表記で辞書を作成
result = {i: j for (i, j) in zip(eto, animal)}
result
{'酉': 'とり', '戌': 'いぬ', '亥': 'いのしし'}
集合
集合の定義
重複を許容しない要素の組み合わせを集合という。
set
関数もしくは、波括弧{}
で囲むことで作成できる。
# 集合を作る
month = {'1月', '2月', '3月', '4月', '5月'}
print(month)
print(set('Python'))
print(set(['Python', 'App']))
print(set( ('Python', 'App') ))
print(set( {'酉': 'とり', '戌': 'いぬ'} ))
{'4月', '2月', '5月', '1月', '3月'}
{'t', 'h', 'n', 'o', 'y', 'P'}
{'Python', 'App'}
{'Python', 'App'}
{'酉', '戌'}
リストの重複要素削除
一度集合に変換することで、リストの重複要素を削除できる。
data = ['スカッシュ', 'バレー', 'ポロ', 'スカッシュ', 'バレー']
# リストから重複を排除した集合を作成
dataSet = set(data)
print(dataSet)
# 集合をリスト化
print(list(dataSet))
{'バレー', 'ポロ', 'スカッシュ'}
['バレー', 'ポロ', 'スカッシュ']
集合同士の演算
それぞれの集合で重複した要素のみの抽出など、演算を行うこともできる。
data1 = {'スカッシュ', 'バレー', 'ポロ'}
data2 = {'スカッシュ', 'バレー', 'セパタクロー'}
data3 = {'スカッシュ', 'バレー', 'キックベース'}
# data1の重複していない要素のみを取り出す
print(data1 - data2)
# data1とdata2で重複する要素のみを取り出す
print(data1 & data2)
# 重複要素を取り除いた集合を作成する
print(data1.union(data2, data3))
# 全てに共通する要素で集合を作成する
print(data1.intersection(data2, data3))
{'ポロ'}
{'バレー', 'スカッシュ'}
{'キックベース', 'バレー', 'ポロ', 'セパタクロー', 'スカッシュ'}
{'バレー', 'スカッシュ'}
関数編
関数の定義
def
キーワードで関数を定義する。
Javaのような括弧は無いため、インデントされた行が関数の本体部分となる。
def calcTax(price):
return price * 1.08
result = calcTax(12)
print('うまい棒は税込み{}円です。'.format(result))
うまい棒は税込み12.96円です。
引数
引数の指定方法
位置引数とキーワード引数の2通りがある。
「仮引数名=値」の形式で引数のデフォルト値を設定することもできる。
通常の引数は省略すると実行時にエラーとなるが、デフォルト値のある引数は省略してもエラーとならない。
def calcTax2(price, rate = 10):
return price + int(price * rate / 100)
# 位置指定の引数で関数呼び出し
print(calcTax2(100, 8))
# パラメータ名指定で関数呼び出し
print(calcTax2(rate = 5, price = 200))
# 一部パラメータ名指定で関数呼び出し
print(calcTax2(500, rate = 8))
# デフォルトパラメータの適用
print(calcTax2(2500))
108
210
540
2750
リストをデフォルト値として使う
関数のデフォルトパラメータは再使用されるため、def appendTest(arg=[])
としてはならない。
(複数回呼び出された時に予期せぬ結果となる可能性がある)
下記の例のように、関数内部でリストを初期化するようにすれば問題は発生しない。
def appendTest(arg=None):
msgList = []
if arg and isinstance(arg, list):
# 引数がリスト型ならば、msgListにコピーしてセット
msgList = arg.copy()
msgList.append('Hello!')
return msgList
print(appendTest())
print(appendTest(['hogehoge']))
print(appendTest())
print(appendTest(3)) # 数値型なので無視される
['Hello!']
['hogehoge', 'Hello!']
['Hello!']
['Hello!']
可変長パラメータ
仮引数名の前に*
を付けると、その引数は可変長となる。
def funcTest(level, *messages):
print(messages)
for msg in(messages):
print(level, msg)
funcTest('INFO', 'あいうえお', 'かきくけこ', 'さしすせそ')
funcTest('DEBUG', 'たちつてと')
('あいうえお', 'かきくけこ', 'さしすせそ')
INFO あいうえお
INFO かきくけこ
INFO さしすせそ
('たちつてと',)
DEBUG たちつてと
辞書型パラメータ
仮引数名の前に**
を付けると、その引数は辞書型となる。
可変長パラメータと同時に使用する場合は、可変長パラメータの後に定義する。
def funcTest2(date, level, *messages, **keywords):
print(date, level, list(messages), keywords)
funcTest2('2021/03/01', 'INFO', 'あいうえお', 'かきくけこ', key1='値1', key2='値2')
2021/03/01 INFO ['あいうえお', 'かきくけこ'] {'key1': '値1', 'key2': '値2'}
様々な関数
高階関数
JavaScriptなどと同様、引数で関数を受け取り、実行することができる。
def printText(text1, text2):
print(text1, '-->', text2)
def execFunction(func, arg1, arg2):
func(arg1, arg2)
execFunction(printText, 'hogehoge', 'piyopiyo')
hogehoge --> piyopiyo
関数内関数
関数の中で関数を定義し、呼び出すこともできる。
def outerFunc(a, b):
def innerFunc(c, d):
return c + d
return innerFunc(a, b)
outerFunc(1, 5)
6
ラムダ式
処理内容が少ない関数は、lambda
キーワードを使うことで、記述をシンプルにできる。
def printNumbers(numbers, func):
for num in numbers:
print(func(num))
prices = [100, 210, 317]
printNumbers(prices, lambda val: '{}円'.format(val))
100円
210円
317円
ジェネレーター関数
return
ではなくyield
で値を返す関数は、next
や反復処理で値を順番に取り出せる。
def generate(str):
for s in str:
yield '「{}」'.format(s)
gen = generate('カールおじさん')
gen2 = generate('!?')
# 反復処理での取り出し
for s in gen:
print(s)
# next関数での取り出し
print(next(gen2))
「カ」
「ー」
「ル」
「お」
「じ」
「さ」
「ん」
「!」
デコレーター
デコレーターを使うと、関数に追加処理を付加できる。
# 引数が必要な場合は、関数を返す関数が入れ子構造となる
def deco(mark):
# 関数をラップするデコレーター
def _deco(func):
def newFunc():
print(mark + 'function calles:' + func.__name__)
return func()
return newFunc
return _deco
# デコレーターを使用
@deco('★')
def hello():
return 'こんにちは!'
print(hello())
★function calles:hello
こんにちは!
おわりに(所感)
使い慣れたJavaScriptなどとの違い(下記)に、はじめは少々戸惑いましたが、比較的シンプルで使いやすい言語であると思いました。
- インデントの深さで関数のブロックが決まる
- キーワード無しで変数宣言が出来てしまう
- ダブルアンダーバーに囲まれた特殊変数(
__name__
など)がたくさんある