<jupyter_start><jupyter_text>Seminar 03 - Functions form submissions with other solution attempts (access by @phystech.edu email):https://docs.google.com/spreadsheets/d/1cV-s5hKuQAAtk1jNDMiaTUvjjBZH_yohHJU05PKWYxw  Task 1return min and max argument (or keyword argument)if 1 argument passed and it is iterable, return min and max of this argument<jupyter_code># decision from seminar
def minmax(*args, **kwargs):
    if len(args) == 1 and not kwargs and hasattr(args[0], '__iter__'):  # isinstance([], list)
        return min(args[0]), max(args[0])
    else:
        all_values = [*args, *(kwargs.values())]
        return min(all_values), max(all_values)
# correct decision that works for minmax(a=[1, 2, 3])
def minmax(*args, **kwargs):
    all_values = [*args, *(kwargs.values())]
    if len(all_values) == 1 and hasattr(all_values[0], '__iter__'):
        collection = all_values[0]
    else:
        collection = all_values
    return min(collection), max(collection)
minmax(1, a=4, b=5, c=6)
[
    minmax([1, 2, 3])              == (1, 3),
    minmax(1, 2, 3)                == (1, 3),
    minmax(1, 2, 3, a=4, b=5, c=6) == (1, 6),
    minmax(1, a=4, b=5, c=6)       == (1, 6),
    minmax(1)                      == (1, 1),
    minmax(a=[1, 2, 3])            == (1, 3),
]
min([1, 2, 3], 1)  # raise error<jupyter_output><empty_output><jupyter_text>Packing & unpacking refresh<jupyter_code>def pack_args(*args, **kwargs):
    return args, kwargs
pack_args(1, 2, 3, a=4, b=5, c=6)
def pack_args_2(x, y, *args, a=None, **kwargs):
    return args, kwargs
pack_args_2(1, 2, 3, a=4, b=5, c=6)<jupyter_output><empty_output><jupyter_text>Task 2return 3 minimal elements from given collection<jupyter_code>from typing import Iterable
def min3(a: Iterable):
    a = a.copy()  # not to change given collection
    return a.pop(a.index(min(a))), a.pop(a.index(min(a))), a.pop(a.index(min(a)))

min3([1, 1, 1, 1])
[
    min3([5, 4, 3, 2, 1]) == (1, 2, 3),
    min3([1, 1, 2, 3])    == (1, 1, 2),
    min3([1, 1, 1, 1])    == (1, 1, 1),
]
a = [5, 4, 3, 2, 1]
min3(a)
a  # should be [5, 4, 3, 2, 1]<jupyter_output><empty_output><jupyter_text>Task 3Create a decorator to print function name and its arguments (including kwargs) before the call and print function result after call<jupyter_code>import functools


def log(func):

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        name = func.__name__
        print(f'{name} function was called with {args} {kwargs}')
        res = func(*args, **kwargs)
        print(f'result is {res}')
        return res

    return wrapper


@log
def foo(bar):
    pass
foo(1)
# 'foo' function was called with args=(1,), kwargs={}
# 'foo' result is None
@log
def pack_args(*args, **kwargs):
    return args, kwargs

print(pack_args.__name__)
pack_args(1, 2, 3, a=4, b=5, c=6)<jupyter_output>pack_args function was called with (1, 2, 3) {'a': 4, 'b': 5, 'c': 6}
result is ((1, 2, 3), {'a': 4, 'b': 5, 'c': 6})<jupyter_text>Function is object in Python<jupyter_code>def foo(bar):
    pass

print(type(foo))
print(dir(type(foo)))<jupyter_output>['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
{'fraction_non_alphanumeric': 0.17686692869174622, 'fraction_numerical': 0.03874227961819203, 'mean_word_length': 4.171262699564586, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '514999', 'license': 'MIT', 'n_tokens_mistral': 1468, 'n_tokens_neox': 1385, 'n_words': 369, 'path': 'week03_functions/seminar/seminar03.ipynb', 'repo_name': 'fortminors/msai-python', 'size': '3562'}