Python functools
• functools.wraps を使用すると、デコレータを適用した関数が元の関数のメタデータ(名前やドキュメント文字列など)を保持することができます。使用しない場合、これらのメタデータは失われます。
• functools.lru_cache を使用すると、関数の結果をキャッシュすることで計算が高速化されます。使用しない場合、毎回計算が行われるため遅くなります。
• functools.partial を使用すると、関数の一部の引数を固定した新しい関数を簡単に作成できます。使用しない場合、毎回関数を再定義する必要があります。
• functools.reduce を使用すると、シーケンスを累積して単一の値に減らす処理が簡潔に書けます。使用しない場合、ループを使って手動で累積計算を行う必要があります。
import functools
# functools.wrapsを使うと、デコレーターを使っても関数の情報が失われません。
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('Something is happening before the function is called.')
result = func(*args, **kwargs)
print('Something is happening after the function is called.')
return result
return wrapper
@my_decorator
def say_hello(name):
"""
この関数にはdocstringがあります。
このdocstringはデコレーターを使うと失われますが、
functools.wrapsを使うことで失われません。"""
print(f'Hello {name}')
say_hello('Bob')
print(say_hello.__name__)
print(say_hello.__doc__)
Something is happening before the function is called.
Hello Bob
Something is happening after the function is called.
say_hello
この関数にはdocstringがあります。
このdocstringはデコレーターを使うと失われますが、
functools.wrapsを使うことで失われません。
# 使わなかった場合
def my_decorator(func):
def wrapper(*args, **kwargs):
print('Something is happening before the function is called.')
result = func(*args, **kwargs)
print('Something is happening after the function is called.')
return result
return wrapper
@my_decorator
def say_hello(name):
"""この関数にはdocstringがあります。
このdocstringはデコレーターを使うと失われます。"""
print(f'Hello {name}')
say_hello('Bob')
print(say_hello.__name__)
print(say_hello.__doc__)
Something is happening before the function is called.
Hello Bob
Something is happening after the function is called.
wrapper
None
functools.lru_cache の比較
使用しなかった場合
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 計算に時間がかかる
使用した場合
import functools
@functools.lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10)) # 計算が高速になる
unctools.partial の比較
使用しなかった場合
def power(base, exponent):
return base ** exponent
def square(base):
return power(base, 2)
def cube(base):
return power(base, 3)
print(square(3)) # 9
print(cube(3)) # 27
使用した場合
import functools
def power(base, exponent):
return base ** exponent
square = functools.partial(power, exponent=2)
cube = functools.partial(power, exponent=3)
print(square(3)) # 9
print(cube(3)) # 27
functools.reduce の比較
使用しなかった場合
numbers = [1, 2, 3, 4, 5]
total_sum = 0
for num in numbers:
total_sum += num
print(total_sum) # 15
使用した場合
import functools
numbers = [1, 2, 3, 4, 5]
total_sum = functools.reduce(lambda x, y: x + y, numbers)
print(total_sum) # 15
この記事が気に入ったらサポートをしてみませんか?