import functools
trace_enabled = False
def trace(func):
@functools.wraps(func)
def inner(*args, **kwargs):
print(func.__name__, args, kwargs)
return func(*args, **kwargs)
return inner if trace_enabled else func
trace_enabled = False
def trace(handle):
# handle - catching args
def decorator(func):
# real decorator
@functools.wraps(func)
def inner(*args, **kwargs):
print(func.__name__, args, kwargs, file=handle)
return func(*args, **kwargs)
return inner if trace_enabled else func
return decorator
def with_arguments(deco):
@functools.wraps(func)
def wrapper(*dargs, **dkwargs):
def decorator(func):
result = deco(func, *dargs, **dkwargs)
functools.update_wrapper(result, func)
return result
return decorator
return wrapper
@with_arguments
def trace(func, handle):
@functools.wraps(func)
def inner(*args, **kwargs):
print(func.__name__, args, kwargs, file=handle)
return func(*args, **kwargs)
return inner
@trace(sys.stderr)
def identity(x):
return x
Oh my fuCng god!!!! 😲😲😲
def trace(func=None, *, handle=sys.stdout):
# with kwarg
if func is None:
return lambda func: trace(func, handle=handle)
# without kwarg
@functools.wraps(func)
def inner(*args, **kwargs):
print(func.__name__, args, kwargs, handle)
return func(*args, **kwargs)
return inner
def timethis(func=None, *, n_iter=100):
if func is None:
return lambda func: timethis(func, n_iter=n_iter)
@functools.wraps(func)
def inner(*args, **kwargs):
print(func.__name__, end=" ... ")
acc = float("inf")
for i in range(n_iter):
tick = time.perf_counter()
result = func(*args, **kwargs)
acc = min(acc, time.perf_counter() - tick)
print(acc)
return result
return inner
result = timethis(sum)(range(10 ** 6))
time.perf_counter # !!!!!!!!!!!!!!!!!!
def lol(val):
lol.val = val
lol(10)
print(lol.val) # 10
def once(func):
@functools.wraps(func)
def inner(*args, **kwargs):
if not inner.called:
inner.called = True # attribute of wrapper
inner.result = func(*args, **kwargs) # returned value
return inner.result
inner.called = False
return inner
@once
def init_settings():
print("Username == Alex")
return 1
init_settings() # Username == Alex
init_settings() #
init_settings() #
def memoized(func):
cache = {}
@functools.wraps(func)
def inner(*args, **kwargs):
key = args + tuple(sorted(kwargs.items()))
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
return inner
def addon(a, b):
return a + b
def pre(cond, message):
def wrapper(func):
@functools.wraps(func)
def inner(*args, **kwargs):
assert cond(*args, **kwargs), message
return func(*args, **kwargs)
return wrapper
@pre(lambda x: x > 0, "negative argument")
def checked_log():
pass
checked_log(-42) # AssertionError: negative argument
def post(cond, message):
def wrapper(func):
@functools.wraps(func)
def inner(*args, **kwargs):
result = func(*args, **kwargs)
assert cond(*args, **kwargs), message
return result
return wrapper
@post(lambda x: not math,isnan(x), "result not a number")
def something():
return 'h'
something() # AssertionError: result not a number
import functools
@functools.lru_cache(maxsize=64)
def cached_func():
pass
cached_func()
cached_func.cache_info() # CacheInfo(hits=65, misses=315, maxsize=64, currsize=64)
# hits - cases when answer were in cache
# mass - cases when answer wasn't in cache
@functools.lru_cache(maxsize=None) # unlimited
def __():
pass
# =====================================
f = functools.partial(sorted, key=lambda p: p[1])
f([('a', 4), ('b', 2)]) # [('b', 2), ('a', 4)]
# =====================================
# reserving for any type
@functools.singledispatch
def pack(obj):
type_name = type(obj).__name__
assert False, f"Unsupported type: {type_name}"
# reserving for int
@pack.register(int)
def _(obj):
return f"I{hex(obj)}"
# reserving for list
@pack.register(list)
def _(obj):
return f"I{'-'.join(str(x) for x in obj)}"
all([1,2,3,0]) # False
all([1,2,3,1]) # True
any([1,0,0,0]) # True
any([0,0,0,0]) # False