初心者のPython3メモ
自分用。適当に追記。
[Python >= 3.7]
コーディング規約
PEP8というのに倣うのがいいらしい
パッケージを任意の場所にインストール
Node.jsで言うところの npm install raiburari --save-dev
。
でも、やらないのか? なんかあまり見かけない
pip install raiburari -t ./basho
検索パスは PYTHONPATH で設定
Pythonは、環境変数 PYTHONPATH
に設定されたパスからモジュールを探す。
↓こういう位置関係のときに……
pytest/
├ main.py
├ sub.by
└ lib/
├ hoge.py
└ piyo
└ kani.py
PYTHONPATH
に何も設定しない場合、main.py
から全て import
するには↓こうなる。
import sub
from lib import hoge
from lib.piyo import kani
print('main!')
print(sub.fn())
print(hoge.fn())
print(kani.fn())
ここで PYTHONPATH
に lib
を設定した場合、同じものを↓こう書けるようになる。
import sub
import hoge
from piyo import kani
print('main!')
print(sub.fn())
print(hoge.fn())
print(kani.fn())
[構文] nullじゃなくてNone
null
じゃなくて None
。is None
, is not None
で判定。
kyomu = None
if kyomu is None:
print('虚無')
else:
print('虚無じゃない')
[構文] インクリメント・デクリメント演算子
無いから += 1
/-= 1
でやる
[構文] 普通の (インデックス番号での) ループ処理
私が思ってる普通の for
ループは無い。range()
を使う。
for i in range(3):
print(i) # -> 0 -> 1 -> 2
for i in range(2, 5):
print(i) # -> 2 -> 3 -> 4
[構文] for ... else, while ... else
for
/while
のあとに else
を書くと、for
/while
の条件が False
になった後の処理を書ける。1回目で False
になっても通る。
for i in range(3):
print(i) # -> 0 -> 1 -> 2
else:
print('!') # -> !
for i in []:
print('来ない')
else:
print('!!') # -> !!
i = 0
while i < 3:
print(i) # -> 0 -> 1 -> 2
i += 1
else:
print('!') # -> !
while False:
print('来ない')
else:
print('!!') # -> !!
[構文] 例外処理
import traceback
try:
# raiseで投げる
raise RuntimeError('awwwwww')
except Exception as e:
# メッセージは例外を文字列にキャストすると出てくる
print(e)
# スタックトレースは traceback で取れる
print(traceback.format_exc())
traceback.print_exc() # これでも同じ
# さらに上に投げる
raise e
else:
# 何も起きなかった場合の処理
print('else!')
finally:
# 最後に必ず行う処理 (ここではexceptでさらにraiseしてるが、ちゃんと実行される)
print('finally!')
[変数] 変数のスコープ
if
の中とか try
の中で定義した変数は外に出ても残ってる
if (True):
a = 1
print(a) # -> 1
try:
b = 2
except:
print('ここには来ない')
print(b) # -> 2
[関数] 引数の初期値とキーワード
def impression(fruit, color, taste='甘い', shape=None):
str = fruit + 'は' + color + '色で'
if shape is not None:
str += shape + 'くて'
str += taste + 'です'
return str
print(impression('りんご', '赤'))
# -> りんごは赤色で甘いです
print(impression(color='黄', fruit='レモン', taste='すっぱい'))
# -> レモンは黄色ですっぱいです
print(impression('メロン', '緑', shape='四角', taste='辛い'))
# -> メロンは緑色で四角くて辛いです
[クラス] 基本
class ParentClass:
parenthensu = '親クラス変数'
class MyClass(ParentClass):
hensu = 'クラス変数'
TEISU = '定数は無い'
_private_hensu = 'プライベートは無い'
def __init__(self):
# コンストラクタ
self.hensu2 = 'クラス変数を生やす'
def fn1(self, a):
return 'fn1です' + a
# クラスメソッド呼び出し
myclass = MyClass()
print(myclass.fn1('お')) # -> fn1ですお
# instanceOf
print(isinstance(myclass, MyClass)) # -> True
print(isinstance(myclass, ParentClass)) # -> True
# 属性を持ってるか
print(hasattr(myclass, 'hensu')) # -> True
print(hasattr(myclass, 'parenthensu')) # -> True
[クラス] メソッドのオーバーロード
無い
[文字列] ヒアドキュメント
# これだと先頭と最後に改行が入る
text = '''
非実在電波少年キリウ君が
月面でチャーハン食ってる
この現実
'''
# 行末に\をつければ改行が入らない
text = '''\
非実在電波少年キリウ君が
月面でチャーハン食ってる
この現実\
'''
# 文頭・文末以外なら気にしなくてOK
text = '''ああああああ'ああああああ!!!'''
# クォートを変える
text = """ああああああああああああ!!!'"""
# \でエスケープする
text = '''ああああああああああああ!!!\''''
# コード上で改行が挟まってれば文末扱いにはならない
text = '''ああああああああああああ!!!'
'''
長い文字列リテラルの定義にはヒアドキュメントや('...' '...')が便利 - Qiita
[文字列] %ってなに?
文字列のフォーマットするやつ
print('%s は %s で %s な %s だ' % ('あいつ', 'ばか', 'あほ', 'くず'))
# -> あいつ は ばか で あほ な くず だ
でもPython3なら .format
を使ったほうがいいらしい
Pythonの%演算子による文字列フォーマット - Qiita
print('{} は {} で {} な {} だ'.format('あいつ', 'くず', 'ごみ', 'かす'))
# -> あいつ は くず で ごみ な かす だ
これでもいい
who = 'あいつ'
curse = 'くず'
print(f'{who} は {curse} だ')
# -> あいつ は くず だ
Python, formatで書式変換(0埋め、指数表記、16進数など) | note.nkmk.me
[文字列] substring
str = 'ABCDEFG'
print(str[0:3])
print(str[:3])
# -> ABC
print(str[3])
# -> D
print(str[3:7])
print(str[3:])
# -> DEFG
print(str[-3])
# -> E
print(str[-3:])
# -> EFG
print(str[:-3])
# -> ABCD
[文字列] 大文字⇔小文字
str = 'aBcDeF'
print(str.upper())
# -> ABCDEF
print(str.lower())
# -> abcdef
[文字列] 正規表現
re
を使う。
「含まれているか」が知りたいなら re.search()
を使う。re.match()
は先頭から一致してないとマッチしない。
import re
if re.search(r'abc', '12345abcde'):
print('マッチした') # こっちくる
else:
print('マッチしない')
正規表現で置換するなら re.sub()
を使う。マッチする箇所全て置換される。
import re
str = 'abcabc'
print(re.sub('ab', '!', s)) # -> !c!c
何回も使うような正規表現は事前に re.compile()
でコンパイルしておける。
import re
pattern = re.compile(r'abc')
if re.search(pattern, '12345abcde'):
print('マッチした') # こっちくる
else:
print('マッチしない')
[数値] 整数の乱数
※これだと10000を含むので注意
import random
print(random.randint(0,10000))
# -> 0 ~ 10000 の乱数
9.6. random — 擬似乱数を生成する — Python 3.6.5 ドキュメント
[リスト] リストのループ処理
list = ['a', 'b', 'c']
for value in list:
print(value) # -> a -> b -> c
list = ['a', 'b', 'c']
for i, value in enumerate(list):
print(i, value) # -> 0 a -> 1 b -> 2 c
list = [
{'a':1, 'b':2},
{'a':3, 'b':4},
]
for item in list:
item['a'] = item['a'] + 1
print(list) # -> [{'a': 2, 'b': 2}, {'a': 4, 'b': 4}]
[リスト] インデックスの有無判定
ずばりそういうのは無い リストの長さと比較するしかない
list = ['a', 'b', 'c']
if 3 < len(list):
print('インデックスある')
else:
print('インデックス無い') # こっちくる
[リスト] リスト同士を結合
list1.extend(list2)
すると、list1
に list2
を結合できる
list1 = [1,2,3]
list2 = [0,4]
list1.extend(list2)
print(list1) # -> [1, 2, 3, 0, 4]
元のリストを壊したくなかったら +
を使う
list1 = [1,2,3]
list2 = [0,4]
list3 = list1 + list2
print(list3) # -> [1, 2, 3, 0, 4]
[リスト] 辞書のリストを特定のキーでソートする
list.sort()
に関数を渡せばできる
import pprint
pp = pprint.PrettyPrinter(indent=4)
list = [
{ 'score': 100, 'name': '鈴木' },
{ 'score': 48, 'name': '佐藤' },
{ 'score': 20, 'name': '山田' },
{ 'score': 75, 'name': '桐生' },
]
list.sort(key=lambda d: d['score'], reverse=True)
pp.pprint(list)
# -> [ {'name': '鈴木', 'score': 100},
# {'name': '桐生', 'score': 75},
# {'name': '佐藤', 'score': 48},
# {'name': '山田', 'score': 20}]
なお上記はlambda式使ってるが、以下と同じ
list = [
{ 'score': 100, 'name': '鈴木' },
{ 'score': 48, 'name': '佐藤' },
{ 'score': 20, 'name': '山田' },
{ 'score': 75, 'name': '桐生' },
]
def sort_by_score(d):
return d['score']
list.sort(key=sort_by_score, reverse=True)
[辞書] キーにクォートは必須
わすれるな
dict = {
msg: 'これは構文エラー'
}
dict = {
'msg': 'こっちが正しい'
}
[辞書] キーに変数を使う
ていうかクォート忘れるとそうなる
name = 'msg'
dict = {
name: '可変キー'
}
print(dict) # -> {'msg': '可変キー'}
[辞書] キーの有無判定
in
, not in
で判定する
dict = { 'key1': 'value1' }
if 'key1' in dict:
print('key1ある') # こっちくる
else:
print('key1無い')
[辞書] キーの有無判定しつつ値取得
dict.get()
使う
dict = { 'key1': 'value1' }
value = dict.get('key1')
print(dict.get('key1', '!')) # -> value1
print(dict.get('key2', '!')) # -> !
print(dict.get('key2')) # -> None
[辞書] キーを除去
del
で消せる。JavaScriptの delete
みたいな
dict = { 'key1': 'value1' }
print(dict['key1']) # -> value1
del dict['key1']
print(dict['key1']) # -> KeyError: 'key1'
[辞書] 辞書同士を結合
dict.update()
ただし元の配列が変化するので注意
dict1 = {
'key1': 'value1',
'key2': 'value2',
}
dict2 = {
'key2': '!?',
'key3': 'value3',
}
dict1.update(dict2)
print(dict1) # -> {'key1': 'value1', 'key2': '!?', 'key3': 'value3'}
Python3.9以降なら |
演算子でできる
dict1 = {
'key1': 'value1',
'key2': 'value2',
}
dict2 = {
'key2': '!?',
'key3': 'value3',
}
print(dict1 | dict2) # -> {'key1': 'value1', 'key2': '!?', 'key3': 'value3'}
[辞書] 辞書をコピー
dict.copy()
でできる
dict = {'key1': 'value1'}
dict1 = dict.copy()
dict1['key1'] = '!!'
dict2 = dict.copy()
dict2['key1'] = '??'
dict['key2'] = 'value2'
print(dict) # -> {'key1': 'value1', 'key2': 'value2'}
print(dict1) # -> {'key1': '!!'}
print(dict2) # -> {'key1': '??'}
ただし入れ子になってて別の辞書を参照してる場合、別の辞書の値はコピーされず、そちらは参照のまま。
dict1 = {'!!': '??'}
dict2 = {
'key1': 'value1',
'key2': dict1
}
print(dict2) # -> {'key1': 'value1', 'key2': {'!!': '??'}}
dict3 = dict2.copy()
# dict1 を変更すると両方変化して見える
dict1['!!'] = '***'
print(dict2) # -> {'key1': 'value1', 'key2': {'!!': '***'}}
print(dict3) # -> {'key1': 'value1', 'key2': {'!!': '***'}}
ディープコピーしたければ以下参照
Python3.7 辞書をclone (ディープコピー) - キリウ君が読まないノート
[辞書] 辞書のループ処理
dict.items()
, dict.keys()
, dict.values()
for [key, value] in dict.items():
print(key, value) # a 1 -> b 2 -> c 3
dict = { 'a': 1, 'b': 2, 'c': 3 }
for key in dict.keys():
print(key) # a -> b -> c
for value in dict.values():
print(value) # 1 -> 2 -> 3
[日付] 現在日時を文字列で取得
from datetime import datetime
print(datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
# -> 2019-02-06 12:41:23.395880
[日付] 日時の計算
8.1. datetime — 基本的な日付型および時間型 — Python 3.6.5 ドキュメント
from datetime import datetime, timedelta
d = datetime(year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
print(d.strftime("%Y-%m-%d %H:%M:%S.%f"))
# -> 2000-01-01 00:00:00.000000
ippungo = d + timedelta(seconds=60)
print(ippungo.strftime("%Y-%m-%d %H:%M:%S.%f"))
# -> 2000-01-01 00:01:00.000000
mirai = d + timedelta(days=1, seconds=1, microseconds=1, milliseconds=1, minutes=1, hours=1, weeks=1)
print(mirai.strftime("%Y-%m-%d %H:%M:%S.%f"))
# -> 2000-01-09 01:01:01.001001
[日付] ISO8601
from datetime import datetime
d = datetime(year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
print(d.isoformat(timespec='hours')) # -> 2000-01-01T00
print(d.isoformat(timespec='minutes')) # -> 2000-01-01T00:00
print(d.isoformat(timespec='seconds')) # -> 2000-01-01T00:00:00
print(d.isoformat(timespec='milliseconds')) # -> 2000-01-01T00:00:00.000
print(d.isoformat(timespec='microseconds')) # -> 2000-01-01T00:00:00.000000