『ルパンの娘』シリーズにハマって以来、著者の他の作品が気になって、『K2 池袋署刑事課 神崎・黒木』なども楽しんだのですが、第56回江戸川乱歩賞受賞となった本作も読み応えがあって十分楽しめめる作品でした。
タイトルの「再会」、意味の重さを感じます。登場人物のその後が幸せであって欲しいなと思います。
『ルパンの娘』シリーズにハマって以来、著者の他の作品が気になって、『K2 池袋署刑事課 神崎・黒木』なども楽しんだのですが、第56回江戸川乱歩賞受賞となった本作も読み応えがあって十分楽しめめる作品でした。
タイトルの「再会」、意味の重さを感じます。登場人物のその後が幸せであって欲しいなと思います。
「Pythonエンジニア育成推進協会監修 Python実践レシピ(2) - Mae向きなブログ」の続きです。
from pathlib import Path TEST_PATH = "/Users/foo/tmp/hoge.pdf" # ファイル名の取得 print(Path(TEST_PATH).name) # 拡張子なしのファイ名の取得 print(Path(TEST_PATH).stem) # 拡張子の取得 print(Path(TEST_PATH).suffix) # 親ディレクトリの取得 print(Path(TEST_PATH).parent) # CWDの取得 print(Path.cwd()) # ユーザホームディレクトリの取得 print(Path.home())
gzipコマンドがない環境でも、python
コマンドの-m
オプションを指定することで、コマンドラインで実行できる。
% python -m gzip -h usage: gzip.py [-h] [--fast | --best | -d] [file ...] A simple command line interface for the gzip module: act like gzip, but do not delete the input file. positional arguments: file optional arguments: -h, --help show this help message and exit --fast compress faster --best compress better -d, --decompress act like gunzip instead of gzip
ZIPファイル中の圧縮されたファイル名に日本語が含まれているとき、環境依存の文字コードでファイル名が格納されている場合があり、注意が必要。
openpyxl
は便利そうですね。thumbnails.py
/tmp/jpeg
は、Pathlib
を用いているのに対し、save_thubnail_path
については、文字列で扱っている点が少し疑問に感じました。あまり気にすることではないのでしょうか?「Pythonエンジニア育成推進協会監修 Python実践レシピ - Mae向きなブログ」の続きです。
join
メソッドについてwords = '''Beautiful is better than ugly. Explicit is better than implicit.'''.split() print(words) print('-'.join(words[:5]))
Ruby
だと、words[...5].join('-')
と書いていたので、join
メソッドの使い方が新鮮に感じます。
>>> import unicodedata >>> unicodedata.lookup('BEER MUG') '🍺' >>> unicodedata.name('🍺') 'BEER MUG'
金額などの精度が求められる計算には、Decimal
を使うようにする。
>>> 100 * 1.10 110.00000000000001 >>> from decimal import Decimal >>> Decimal('100') * Decimal('1.10') Decimal('110.00')
rrule
はカレンダーアプリケーションなどでよく使われる、繰り返しルールを指定するために使用する。
defaultdict
>>> from collections import defaultdict >>> dataset = [('九州', '福岡'), ('関東', '東京'), ('近畿', '大阪'), ('九州', '宮崎'), ('関東', '神奈川')] >>> d = defaultdict(list) >>> for region, prefecture in dataset: ... d[region].append(prefecture) ... >>> list(d.items()) [('九州', ['福岡', '宮崎']), ('関東', ['東京', '神奈川']), ('近畿', ['大阪'])]
CPU数を取得する。
>>> import os >>> os.cpu_count() 8
Python
を勉強しようと思ったことはこれまでに何度もあるのですが、仕事などで、ちょっとした処理を行うときなどは、つい使い慣れたRuby
で書いてしまうので、なかなかPython
の技術が上達せずにここまできました。
2022年の目標としてPython
をしっかり学んでみようと思います。
以下は、『Python実践レシピ』を読みながら気になることをメモしたものです。
仮想環境について、
1. 仮想環境の作成
python -m venv dir_name
2. 仮想環境の有効化
source dir_name/bin/activate
3. 仮想環境の無効化
deactivate
Pythonには、PEP 8というスタイルガイドがあり、Pythonの開発者の間ではPEP 8に従うことが一般的
with
文に渡すオブジェクトをコンテキストマネージャーという。with文が実行されると、
__enter__()
メソッドの処理が実行される。with
ブロックが終了したあとに、__exit__()
が実行される。@contextlib.contextmanager
というデコレータを使用してジェネレータ関数を記述することで、コンテキストマネージャーを定義できる。
>>> def multiplier(): ... num = 1 ... while True: ... yield num ... num *= 2 ... >>> gen = multiplier() >>> dir(gen) # ジェネレーターオブジェクトの`__next__()`メソッドが呼び出される ['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw'] >>> next(gen) 1 >>> next(gen) 2 >>> next(gen) 4
>>> def sample_func(a, b, c=[]): ... c.append(a + b) ... return c ... >>> sample_func(1, 2) [3] >>> sample_func(3, 4) [3, 7] >>> sample_func(5, 6) [3, 7, 11]
実行結果は、[3], [7], [11]
となって欲しいのですが、原因は、デフォルト値のリストオブジェクトは関数作成時に一度だけ作成され、そのあともこのリストオブジェクトが再利用されるためだそうです。ちょっと直感と動作が違うような気がします。
解決策は、以下の通りです。
>>> def sample_func(a, b, c=None): ... if c is None: ... c = [] ... c.append(a + b) ... return c ... >>> sample_func(1, 2) [3] >>> sample_func(3, 4) [7] >>> sample_func(5, 6) [11]
ちなみに、Rubyだと以下のように動作します。
irb(main):005:1* def sample_func(a, b, c = []) irb(main):006:1* c.append(a + b) irb(main):007:1* c irb(main):008:0> end => :sample_func irb(main):009:0> sample_func(1, 2) => [3] irb(main):010:0> sample_func(3, 4) => [7] irb(main):011:0> sample_func(5, 6) => [11]
def my_decorator(func): def wrap_function(): """wrap_functionのドキュメントです""" func() print(f'function: {func.__name__} called') return wrap_function def greeting(): """greetingのドキュメントです""" print('こんにちは') greeting = my_decorator(greeting) print(greeting.__name__) print(greeting.__doc__) greeting()
実行すると、
wrap_function wrap_functionのドキュメントです こんにちは function: greeting called
となり、もとの関数名やdocstring
が失われる。
def my_decorator(func): def wrap_function(): """wrap_functionのドキュメントです""" func() print(f'function: {func.__name__} called') return wrap_function @my_decorator def greeting(): """greetingのドキュメントです""" print('こんにちは') print(greeting.__name__) print(greeting.__doc__) greeting()
この方法でも、デコレータ関数を作成し代入文を使用する例と同様の実行結果となる。
from functools import wraps def my_decorator(func): @wraps(func) # この1文を足す def wrap_function(): """wrap_functionのドキュメントです""" func() print(f'function: {func.__name__} called') return wrap_function @my_decorator def greeting(): """greetingのドキュメントです""" print('こんにちは') print(greeting.__name__) print(greeting.__doc__) greeting()
実行すると、以下のようになり、名前やdocstring
をもとのデコレート対象の関数のものに設定してくれる。通常、デコレーターを作成するときは、functools.wraps
を使用するとよい。
greeting greetingのドキュメントです こんにちは function: greeting called
from dataclasses import dataclass @dataclass class User: name: str age: int address: str user = User('mae', 20, 'Miyazaki') print(user)
def say_hello(name: str) -> str: return f'Hello, {name}' print(say_hello('Python')) print(say_hello(0))
を実行すると、以下のようになり、実行することはできる。
Hello, Python Hello, 0
mypyによる静的型チェックを行うと、以下のように出力され、say_hello
にint
が渡されているとエラーが出力される。
type_hint_prac.py:5: error: Argument 1 to "say_hello" has incompatible type "int"; expected "str" Found 1 error in 1 file (checked 1 source file)
「マスカレード」シリーズの4冊目読了。毎回、楽しみに読んできましたが、今回で終わりなのでしょうか。少し、寂しさも感じますね。
『K2 池袋署刑事課 神崎・黒木』を読み終えたばかりですが、続きが気になって読んでみました。
読み進めるほど、ストーリが絶妙に絡み合っていく心地よさを感じることができていいですね。前作以上に、楽しめる本でした。神崎・黒木の活躍を今後も期待したいですね。