Skip to content

2. Сабуров Ярослав Семенович. 614 - #79

Open
Nerey999 wants to merge 15 commits into
python-department:mainfrom
Nerey999:task2
Open

Nerey999 wants to merge 15 commits into
python-department:mainfrom
Nerey999:task2

Conversation

@Nerey999

@Nerey999 Nerey999 commented Oct 2, 2026

Copy link
Copy Markdown

No description provided.

@github-actions github-actions Bot added the 614 label Oct 2, 2026

@EvgrafovMichail EvgrafovMichail left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хорошее и интересное решение. Отдельный плюс - наличие юнит тестов.

Очень обидно снижать вам балл за копипасту



# ============================================================
# Helpers

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хелперы для подготовки данных для тестов в pytest обычно оформляются с помощью фикстур:
https://docs.pytest.org/en/stable/explanation/fixtures.html

@pytest.mark.parametrize(
("raw", "expected"),
[
("12.999", "13.00"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для оформления тесткейсов лучше использовать pytest.param. Так вы сможете явно сгруппировать данные для тесткейса и связать с ними читаемый ID:
https://docs.pytest.org/en/stable/example/parametrize.html#set-marks-or-test-id-for-individual-parametrized-test



class TestCreateProduct:
def test_success_adds_normalized_product(self) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Старайтесь придерживаться паттерна AAA во всех тестах.

Comment thread src/part2/cart.py


def dict_to_cart_line(line: dict[int, Any]) -> CartLine:
return tuple(x[1] for x in sorted(line.items()))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Забавно, что mypy на это не ругается. Формально тип выходного значения tuple[Any, ...], т.к. тип значений словаря - Any, а dict[int, Any] не дает гарантий, что в словаре будет два объекта. Но т.к. функция служебная, не буду придираться.

А еще ее можно было реализовать без явного индексирования:

Suggested change
return tuple(x[1] for x in sorted(line.items()))
return tuple(val for _, val in sorted(line.items()))

Comment thread src/part2/cart.py
LINE_QUANTITY_INDEX: Final = 1


def dict_to_cart_line(line: dict[int, Any]) -> CartLine:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если функция служебная, можно было явно на это указать, назвав ее так:

Suggested change
def dict_to_cart_line(line: dict[int, Any]) -> CartLine:
def _dict_to_cart_line(line: dict[int, Any]) -> CartLine:

Comment thread src/part2/cart.py


def find_cart_line(cart: list[CartLine], product_id: int) -> CartLine | None:
line = [x for x in cart if x[LINE_PRODUCT_ID_INDEX] == product_id]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Стоило ли использовать для реализации этой функции списковое включение? Так вы гарантированно обойдете все элементы корзины. При использовании явного итерирования в цикле for вы можете выйти из цикла сразу после обнаружения нужной позиции и сэкономить на этом ресурсы.

Comment thread src/part2/crud.py
from .utils import normalize_price


def dict_to_product(record: dict[int, Any]) -> Product:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это один в один дублирование функции dict_to_cart_line. Можно было определить одну служебную функцию в utils.py: convert_dict_to_tuple. Тело функции было бы таким же, а тип возвращаемого значения: tuple[Any, ...]. А вызывающая сторона сама бы выводила нужный тип с помощью функции typing.cast

Comment thread src/part2/cart.py
storage, product_id, (product[NAME_INDEX], product[PRICE_INDEX], new_quantity)
)

dict_line = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я бы унес создание словаря в функцию dict_to_cart_line. А dict_to_cart_line переименовал бы в create_cart_line. Тогда эта функция выглядела бы так:

def create_cart_line(
    product_id: int,
    quantity: int,
) -> CartLine:
    cart_line_dict = {
        LINE_PRODUCT_ID_INDEX: product_id,
        LINE_QUANTITY_INDEX: quantity,
    }
    
    return tuple(val for _, val in sorted(cart_line_dict.items()))

За счет этого вы бы избежали дублирования кода создания словаря, и логику создания позиции в корзине инкапсулировали бы полностью. Одни плюсы. А так, вынужден снизить вам балл за копипасту и нарушение критерия S1

Comment thread src/part2/crud.py
if fields[0] in [x[NAME_INDEX] for x in storage]:
print(f"product name {fields[0]} is already taken")
return None
dict_record = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/part2/crud.py
"""
# TODO: реализуйте функцию
return (0, "", Decimal(0), 0)
record = [x for x in storage if x[PRODUCT_ID_INDEX] == product_id]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants