diff --git a/README.md b/README.md index 8688e02..e8f8817 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -ООП и работа с API +Netology PD-97 diff --git a/decorators/log_task_02_1.log b/decorators/log_task_02_1.log new file mode 100644 index 0000000..f1668d7 --- /dev/null +++ b/decorators/log_task_02_1.log @@ -0,0 +1,38 @@ +{ + "timestamp": "2024-04-12 16:47:00.372140", + "name": "hello_world", + "args": [], + "kwargs": {}, + "result": "Hello World" +}, +{ + "timestamp": "2024-04-12 16:47:00.372719", + "name": "summator", + "args": [ + 2, + 2 + ], + "kwargs": {}, + "result": 4 +}, +{ + "timestamp": "2024-04-12 16:47:00.373231", + "name": "div", + "args": [ + 6, + 2 + ], + "kwargs": {}, + "result": 3.0 +}, +{ + "timestamp": "2024-04-12 16:47:00.373578", + "name": "summator", + "args": [ + 4.3 + ], + "kwargs": { + "b": 2.2 + }, + "result": 6.5 +}, diff --git a/decorators/log_task_02_2.log b/decorators/log_task_02_2.log new file mode 100644 index 0000000..f484da7 --- /dev/null +++ b/decorators/log_task_02_2.log @@ -0,0 +1,38 @@ +{ + "timestamp": "2024-04-12 16:47:00.374138", + "name": "hello_world", + "args": [], + "kwargs": {}, + "result": "Hello World" +}, +{ + "timestamp": "2024-04-12 16:47:00.375032", + "name": "summator", + "args": [ + 2, + 2 + ], + "kwargs": {}, + "result": 4 +}, +{ + "timestamp": "2024-04-12 16:47:00.375575", + "name": "div", + "args": [ + 6, + 2 + ], + "kwargs": {}, + "result": 3.0 +}, +{ + "timestamp": "2024-04-12 16:47:00.375831", + "name": "summator", + "args": [ + 4.3 + ], + "kwargs": { + "b": 2.2 + }, + "result": 6.5 +}, diff --git a/decorators/log_task_02_3.log b/decorators/log_task_02_3.log new file mode 100644 index 0000000..fc1d3d9 --- /dev/null +++ b/decorators/log_task_02_3.log @@ -0,0 +1,38 @@ +{ + "timestamp": "2024-04-12 16:47:00.376093", + "name": "hello_world", + "args": [], + "kwargs": {}, + "result": "Hello World" +}, +{ + "timestamp": "2024-04-12 16:47:00.376384", + "name": "summator", + "args": [ + 2, + 2 + ], + "kwargs": {}, + "result": 4 +}, +{ + "timestamp": "2024-04-12 16:47:00.376543", + "name": "div", + "args": [ + 6, + 2 + ], + "kwargs": {}, + "result": 3.0 +}, +{ + "timestamp": "2024-04-12 16:47:00.376698", + "name": "summator", + "args": [ + 4.3 + ], + "kwargs": { + "b": 2.2 + }, + "result": 6.5 +}, diff --git a/decorators/log_task_03_1.log b/decorators/log_task_03_1.log new file mode 100644 index 0000000..3efdeb3 --- /dev/null +++ b/decorators/log_task_03_1.log @@ -0,0 +1,9 @@ +{ + "name": "new_function", + "timestamp": "2024-04-12 16:46:58.412284", + "args": [ + "10006" + ], + "kwargs": {}, + "result": "\u0410\u0440\u0438\u0441\u0442\u0430\u0440\u0445 \u041f\u0430\u0432\u043b\u043e\u0432" +}, diff --git a/decorators/main.log b/decorators/main.log new file mode 100644 index 0000000..9b6239d --- /dev/null +++ b/decorators/main.log @@ -0,0 +1,48 @@ +{ + "name": "hello_world", + "timestamp": "2024-04-12 16:40:02.552160", + "args": [], + "kwargs": {}, + "result": "Hello World" +}, +{ + "name": "summator", + "timestamp": "2024-04-12 16:40:02.552166", + "args": [ + 2, + 2 + ], + "kwargs": {}, + "result": 4 +}, +{ + "name": "div", + "timestamp": "2024-04-12 16:40:02.552167", + "args": [ + 6, + 2 + ], + "kwargs": {}, + "result": 3.0 +}, +{ + "name": "summator", + "timestamp": "2024-04-12 16:40:02.552166", + "args": [ + 4.3 + ], + "kwargs": { + "b": 2.2 + }, + "result": 6.5 +}, +{ + "name": "summator", + "timestamp": "2024-04-12 16:40:02.552166", + "args": [], + "kwargs": { + "a": 0, + "b": 0 + }, + "result": 0 +}, diff --git a/decorators/modules/__init__.py b/decorators/modules/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/decorators/modules/client.py b/decorators/modules/client.py new file mode 100644 index 0000000..2d97c14 --- /dev/null +++ b/decorators/modules/client.py @@ -0,0 +1,76 @@ +documents = [ + {"type": "passport", "number": "2207 876234", "name": "Василий Гупкин"}, + {"type": "invoice", "number": "11-2", "name": "Геннадий Покемонов"}, + {"type": "insurance", "number": "10006", "name": "Аристарх Павлов"}, + {"type": "driver license", "number": "5455 028765", "name": "Василий Иванов"}, +] + +directories = { + '1': ['2207 876234', '11-2', '5455 028765'], + '2': ['10006'], + '3': [] +} + +### My +def get_name(doc_number): + result = "Документ не найден" + + for document in documents: + if doc_number in document["number"]: + result = document["name"] + + return result + + +def get_directory(doc_number): + result = "Полки с таким документом не найдено" + + for number in directories: + if doc_number in directories[number]: + result = number + + return result + + +def add(document_type, number, name, shelf_number): + new_document = {"type": document_type, "number": number, "name": name} + documents.append(new_document) + + if shelf_number in directories: + if number not in directories[str(shelf_number)]: + directories[str(shelf_number)].append(str(number)) + else: + directories[str(shelf_number)] = [str(number)] + +### Netology +def get_name(doc_number): + for document in documents: + if document['number'] == doc_number: + return document['name'] + return "Документ не найден" + + +def get_directory(doc_number): + for number, docs in directories.items(): + if doc_number in docs: + return number + return "Полки с таким документом не найдено" + + +def add(document_type, number, name, shelf_number): + new_doc = {"type": document_type, "number": number, "name": name} + documents.append(new_doc) + if shelf_number in directories: + directories[shelf_number].append(number) + else: + directories[shelf_number] = [number] + + +if __name__ == '__main__': + print(get_name("10006")) + print(get_directory("11-2")) + print(get_name("101")) + add('international passport', '311 020203', 'Александр Пушкин', 3) + print(get_directory("311 020203")) + print(get_name("311 020203")) + print(get_directory("311 020204")) diff --git a/decorators/task_01.py b/decorators/task_01.py new file mode 100644 index 0000000..5ae9ea5 --- /dev/null +++ b/decorators/task_01.py @@ -0,0 +1,77 @@ +import os +import json +from datetime import datetime + + +def logger(old_function): + log_info = {} + + log_info.update({ + "name": old_function.__name__, + "timestamp": datetime.now() + }) + + def new_function(*args, **kwargs): + result = old_function(*args, **kwargs) + + log_info.update({ + "args": args, + "kwargs": kwargs, + "result": result + }) + + json_object = json.dumps(log_info, indent=4, default=str) + + with open('main.log', "a+") as outfile: + outfile.writelines(json_object + ",\n") + + return result + + return new_function + + +def test_1(): + path = 'main.log' + if os.path.exists(path): + os.remove(path) + + @logger + def hello_world(): + return 'Hello World' + + @logger + def summator(a, b=0): + return a + b + + @logger + def div(a, b): + return a / b + + # hello_world + assert 'Hello World' == hello_world(), "Функция возвращает 'Hello World'" + + # summator + result = summator(2, 2) + assert isinstance(result, int), 'Должно вернуться целое число' + assert result == 4, '2 + 2 = 4' + + # div + result = div(6, 2) + assert result == 3, '6 / 2 = 3' + + # main.log + assert os.path.exists(path), 'файл main.log должен существовать' + + summator(4.3, b=2.2) + summator(a=0, b=0) + + with open(path) as log_file: + log_file_content = str(log_file.read()) + + assert 'summator' in log_file_content, 'должно записаться имя функции' + for item in (4.3, 2.2, 6.5): + assert str(item) in log_file_content, f'{item} должен быть записан в файл' + + +if __name__ == '__main__': + test_1() diff --git a/decorators/task_02.py b/decorators/task_02.py new file mode 100644 index 0000000..52e5b44 --- /dev/null +++ b/decorators/task_02.py @@ -0,0 +1,73 @@ +import os +import json +from datetime import datetime + + +def logger(path): + log_info = {} + + def __logger(old_function): + def new_function(*args, **kwargs): + result = old_function(*args, **kwargs) + + log_info.update({ + "timestamp": datetime.now(), + "name": old_function.__name__, + "args": args, + "kwargs": kwargs, + "result": result + }) + + json_object = json.dumps(log_info, indent=4, default=str) + + with open(path, "a+") as outfile: + outfile.writelines(json_object + ",\n") + + return result + + return new_function + + return __logger + + +def test_2(): + paths = ('log_task_02_1.log', 'log_task_02_2.log', 'log_task_02_3.log') + + for path in paths: + if os.path.exists(path): + os.remove(path) + + @logger(path) + def hello_world(): + return 'Hello World' + + @logger(path) + def summator(a, b=0): + return a + b + + @logger(path) + def div(a, b): + return a / b + + assert 'Hello World' == hello_world(), "Функция возвращает 'Hello World'" + result = summator(2, 2) + assert isinstance(result, int), 'Должно вернуться целое число' + assert result == 4, '2 + 2 = 4' + result = div(6, 2) + assert result == 3, '6 / 2 = 3' + summator(4.3, b=2.2) + + for path in paths: + assert os.path.exists(path), f'файл {path} должен существовать' + + with open(path) as log_file: + log_file_content = str(log_file.read()) + + assert 'summator' in log_file_content, 'должно записаться имя функции' + + for item in (4.3, 2.2, 6.5): + assert str(item) in log_file_content, f'{item} должен быть записан в файл' + + +if __name__ == '__main__': + test_2() \ No newline at end of file diff --git a/decorators/task_03.py b/decorators/task_03.py new file mode 100644 index 0000000..2c52a84 --- /dev/null +++ b/decorators/task_03.py @@ -0,0 +1,50 @@ +import os +import json +from datetime import datetime +from modules.client import get_name + + +def logger(old_function): + log_info = {} + + log_info.update({ + "name": old_function.__name__, + "timestamp": datetime.now() + }) + + def new_function(*args, **kwargs): + result = old_function(*args, **kwargs) + + log_info.update({ + "args": args, + "kwargs": kwargs, + "result": result + }) + + json_object = json.dumps(log_info, indent=4, default=str) + + with open('log_task_03_1.log', "a+") as outfile: + outfile.writelines(json_object + ",\n") + + return result + + return new_function + + +def main(): + path = 'log_task_03_1.log' + + if os.path.exists(path): + os.remove(path) + + @logger + def new_function(name): + result = get_name(name) + + return result + + print(new_function("10006")) + + +if __name__ == '__main__': + main() diff --git a/iterators_generators_yield/solution.py b/iterators_generators_yield/solution.py new file mode 100644 index 0000000..7c7e3f6 --- /dev/null +++ b/iterators_generators_yield/solution.py @@ -0,0 +1,214 @@ +import types +from itertools import chain + + +# _________________________ +# task 1 + +class FlatIteratorV1: + + def __init__(self, list_of_list): + self.list_of_list = list_of_list + + def __iter__(self): + self.cursor_inner = -1 + self.cursor_outer = 0 + return self + + def __next__(self): + self.cursor_inner += 1 + if self.cursor_inner >= len(self.list_of_list[self.cursor_outer]): + self.cursor_outer += 1 + self.cursor_inner = 0 + if self.cursor_outer >= len(self.list_of_list): + raise StopIteration + return self.list_of_list[self.cursor_outer][self.cursor_inner] + + +class FlatIteratorV2: + + def __init__(self, list_of_list): + self.list_of_list = list_of_list + + def __iter__(self): + self.iterators = iter(iter(l) for l in self.list_of_list) + self.current_iter = next(self.iterators) + return self + + def __next__(self): + try: + next_item = next(self.current_iter) + except StopIteration: + self.current_iter = next(self.iterators) + next_item = next(self.current_iter) + return next_item + + +class FlatIteratorV3: + + def __init__(self, list_of_list): + self.list_of_list = list_of_list + + def __iter__(self): + self.flat_iter = chain.from_iterable(self.list_of_list) + return self + + def __next__(self): + return next(self.flat_iter) + + +class FlatIteratorV4: + + def __init__(self, list_of_list): + self.list_of_list = list_of_list + + def __iter__(self): + return chain.from_iterable(self.list_of_list) + + +# _________________________ +# task 2 + +def flat_generator_v1(list_of_lists): + for inner_list in list_of_lists: + for item in inner_list: + yield item + + +def flat_generator_v2(list_of_lists): + for inner_list in list_of_lists: + yield from inner_list + + +def flat_generator_v3(list_of_lists): + for item in chain.from_iterable(list_of_lists): + yield item + + +def flat_generator_v4(list_of_lists): + return (item for item in chain.from_iterable(list_of_lists)) + +# _________________________ +# task 3 + + +class FlatIteratorHard: + + def __init__(self, list_of_list): + self.list_of_list = list_of_list + + def __iter__(self): + self.iters_stack = [iter(self.list_of_list)] + return self + + def __next__(self): + while self.iters_stack: + try: + next_item = next(self.iters_stack[-1]) + # пытаемся получить следующий элемент + except StopIteration: + self.iters_stack.pop() + # если не получилось, значит итератор пустой + continue + + if isinstance(next_item, list): + # если следующий элемент оказался списком, то + # добавляем его итератор в стек + self.iters_stack.append(iter(next_item)) + + else: + return next_item + raise StopIteration + +# _________________________ +# task 4 + + +def flat_generator_v5(list_of_list): + for i in list_of_list: + if isinstance(i, list): + for j in flat_generator_v5(i): + yield j + else: + yield i + + +def test_task_1(): + + list_of_lists_1 = [ + ['a', 'b', 'c'], + ['d', 'e', 'f', 'h', False], + [1, 2, None] + ] + + for IteratorClass in (FlatIteratorV1, FlatIteratorV2, FlatIteratorV3, FlatIteratorV4): + + for flat_iterator_item, check_item in zip( + IteratorClass(list_of_lists_1), + ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None] + ): + assert flat_iterator_item == check_item + + assert list(IteratorClass(list_of_lists_1)) == ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None] + + +def test_task_2(): + + list_of_lists_1 = [ + ['a', 'b', 'c'], + ['d', 'e', 'f', 'h', False], + [1, 2, None] + ] + + for yield_function in (flat_generator_v1, flat_generator_v2, flat_generator_v3, flat_generator_v4): + + for flat_iterator_item, check_item in zip( + yield_function(list_of_lists_1), + ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None] + ): + assert flat_iterator_item == check_item + + assert list(yield_function(list_of_lists_1)) == ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None] + + assert isinstance(yield_function(list_of_lists_1), types.GeneratorType) + + +def test_task_3(): + list_of_lists_2 = [ + [['a'], ['b', 'c']], + ['d', 'e', [['f'], 'h'], False], + [1, 2, None, [[[[['!']]]]], []] + ] + for flat_iterator_item, check_item in zip( + FlatIteratorHard(list_of_lists_2), + ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None, '!'] + ): + assert flat_iterator_item == check_item + + assert list(FlatIteratorHard(list_of_lists_2)) == ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None, '!'] + + +def test_task_4(): + list_of_lists_2 = [ + [['a'], ['b', 'c']], + ['d', 'e', [['f'], 'h'], False], + [1, 2, None, [[[[['!']]]]], []] + ] + + for flat_iterator_item, check_item in zip( + flat_generator_v5(list_of_lists_2), + ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None, '!'] + ): + assert flat_iterator_item == check_item + + assert list(flat_generator_v5(list_of_lists_2)) == ['a', 'b', 'c', 'd', 'e', 'f', 'h', False, 1, 2, None, '!'] + + assert isinstance(flat_generator_v5(list_of_lists_2), types.GeneratorType) + + +if __name__ == '__main__': + + test_task_1() + test_task_2() + test_task_3() + test_task_4()