はじめに
弱々Pythonエンジニアがpython3.8の新機能を一部触ってみました。
よくわからないものはすっ飛ばしてます(ビルドだプロファイルだなんだのは飛ばしてます)。
詳しくは公式ドキュメント参照
セイウチ演算子
大きな構文の一部として、変数に値を割り当てる新しい構文 := が追加されました。 この構文は セイウチの目と牙 に似ているため、「セイウチ演算子」の愛称で知られています。
array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# python3.8以前
# n = len(array) > 10
# if n:
# print(f"List is too long ({n} elements, expected <= 10)")
# python3.8
if n := len(array) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
出力結果
List is too long (True elements, expected <= 10)
判定と一緒に変数宣言できる感じ??
while文や内包表記でも使用できるので詳しくは公式ドキュメント参照
位置専用引数
関数の引数が位置引数として指定されねばならずキーワード引数としては指定できないことを表す、新しい構文 / を追加しました。この構文は、help() で Larry Hasting の Argument Clinic でアノテートした C関数を表示したときと同じ表記です。
正しい関数呼び出し
def profile(first_name, last_name, /, gender, age, *, zip_code, address):
print(f'\
姓:{first_name}\n\
名:{last_name}\n\
性:{gender}\n\
歳:{age}\n\
〒:{zip_code}\n\
住:{address}')
profile('鈴木', '一郎', '男', 99, zip_code='000-0000', address='宇宙') # OK
profile('鈴木', '一郎', '男', age=99, zip_code='000-0000', address='宇宙') # OK
profile('鈴木', '一郎', gender='男', age=99, zip_code='000-0000', address='宇宙') # OK
引数は左から順に、
位置引数:first_name
, last_name
位置引数でもあり、キーワード引数でもある:gender
, age
キーワード引数:zip_code
, address
誤った関数呼び出し
profile('鈴木', '一郎', gender='男', 99, zip_code='000-0000', address='宇宙') # SyntaxError: positional argument follows keyword argument
profile('鈴木', '一郎', age=99, '男', zip_code='000-0000', address='宇宙') # SyntaxError: positional argument follows keyword argument
profile('鈴木', '一郎', '男', 99, '000-0000', address='宇宙') # TypeError: profile() takes 4 positional arguments but 5 positional arguments (and 1 keyword-only argument) were given
profile('鈴木', '一郎', '男', 99, zip_code='000-0000', '宇宙') # SyntaxError: positional argument follows keyword argument
キーワード引数としての利用を排除
/
より前の引数は位置引数になるので、python3.8以前ではできていた以下のような呼び出し方を排除できるようになりました。
位置引数として強制させることができるので遠慮なく引数名を変更できますね!!!
# python3.8以前は位置引数としても、キーワード引数としても利用できた。
def profile(first_name, last_name):
print(f'{first_name} {last_name}')
profile2(first_name='吉田', last_name='花子') # 吉田 花子
...
..
.
# python3.8位置専用引数 / を使用
def profile(first_name, last_name, /):
print(f'{first_name} {last_name}')
profile2(first_name='吉田', last_name='花子') # TypeError: profile2() got some positional-only arguments passed as keyword arguments: 'first_name, last_name'
任意のキーワード引数を受け取るこんな書き方もできるよ。
def profile(first_name, last_name, /, **kwargs):
print(f'{first_name} {last_name} {kwargs}')
profile('吉田', '花子', first_name='鈴木', last_name='一郎') # 吉田 花子 {'first_name': '鈴木', 'last_name': '一郎'}
これにより、任意のキーワード引数を受け取る関数やメソッドを定義するのが、ぐんとシンプルになります。
と公式にありますが、弱々エンジニアなので旨味がわかってません。
キャッシュファイルを別の場所に格納する機能
暗黙のバイトコードキャッシュは、デフォルトでは各ソースコードのディレクトリ内の pycache サブディレクトリを使用しますが、新たに追加された環境変数 PYTHONPYCACHEPREFIX (またはコマンドラインオプション -X pycache_prefix) を指定すると、ソースコードと分離されたディレクトリツリーに格納されるようになります。
キャッシュの場所は sys.pycache_prefix で参照できます(pycache を使用する場合は:const:None になります)。
うまく検証できなかったので、とりあえずスルー。。。
フォーマット済み文字列リテラル(f-string)で「=」指定子が有効になった
string = 'エフストリング'
# python3.8.0 以前
print(f'{string}') # エフストリング
# python3.8.0
print(f'{string=}') # string='エフストリング'
デバッグで役立ちそう(小並感)
dict と dictview は、reversed() を使って逆順でイテレートすることが可能に
python3.7までは、dict
をreversed
で逆順にしようとするとTypeError: 'dict' object is not reversible
になってしまいます。
# python3.8.0 以前
dictionary = {'a': 1, 'b': 2, 'c': 3}
for d in reversed(dictionary):
print(d)
>> TypeError: 'dict' object is not reversible
python3.8からはそれが可能になりました!
# python3.8.0 以前
dictionary = {'a': 1, 'b': 2, 'c': 3}
for d in reversed(dictionary):
print(d)
>> c
>> b
>> a
collections.namedtuple() の _asdict() メソッドがdictを返すようになった
そもそもnamedtupleって何ぞやって方はこちらにわかりやすく解説があります!!!
python3.8以前はOrderedDict
を返すようになっていました。
import collections
Human = collections.namedtuple('Human', ['first_name', 'last_name', 'age'])
human = Human('yamada', 'taro', 25)
print(human._asdict())
>> OrderedDict([('first_name', 'yamada'), ('last_name', 'taro'), ('age', 25)])
python3.8ではDictを返してくれるようになりました!
import collections
from collections import OrderedDict
Human = collections.namedtuple('Human', ['first_name', 'last_name', 'age'])
human = Human('yamada', 'taro', 25)
print(human._asdict())
# print(OrderedDict(human._asdict())) # 3.8でもOrderedDict特有の機能を使いたい場合はキャストして使用することが推奨されています。
>> {'first_name': 'yamada', 'last_name': 'taro', 'age': 25}
csv.DictReaderもdictを返すようになった
この変更によって、順序を保ちながら、より高速にかつメモリの使用量を減らして実行できます。
らしいです。やったぜ。
datetimeモジュールに2つメソッドが追加
ISO の規定に沿った年、週番号、曜日によって、date や datetime オブジェクトを作成するメソッド datetime.date.fromisocalendar() と datetime.datetime.fromisocalendar() が追加されました; これは、各クラスの isocalendar メソッドの逆を行うものです。
なんのこっちゃ。
出力してみた。
from datetime import datetime
date = datetime.now() # 2020-03-06(時分秒省略)
print(date.isocalendar()) # (2020, 10, 5)
print(date.fromisocalendar(2020, 4, 1)) # 2020-01-20 00:00:00
print(datetime.fromisocalendar(2020, 4, 1)) # 2020-01-20 00:00:00
まずは既存のisocalendar()
2020-03-06は
2020年 の 10週目 金(5)曜日
3.8で追加されたfromisocalendar
print(date.fromisocalendar(2020, 4, 1)) # 2020-01-20 00:00:00
引数の詳細は左から順に西暦
, 週
, 曜日
``2020年 の 4週目 月(1)曜日
①は一旦ここまで
疲れたのでこれにて終了。
②もそのうち出します。(自己満)