Как уменьшить ворсистость при работе со списками и использовании mypy?

1

Я просто писал такие вещи на работе и задавался вопросом, есть ли какой-нибудь питонический способ уменьшить посторонние вещи, связанные с списком, итератором и обработкой заданий в Item.display().

Есть ли еще какой-нибудь питонический способ борьбы с фильтрацией и трансформацией в Item.display()?

Есть ли способ использовать другой тип для упрощения ввода?

import unittest
from dataclasses import dataclass, field
from typing import Union, Tuple, List, Iterator

@dataclass
class Category:
    id: str
    name: str = field(compare=False)
    canonical: Union['Category', None] = field(compare=False)

    def __hash__(self)->int:
        return self.id.__hash__()

    def unalias(self)->'Category':
        #There could be more tests here
        if self.canonical:
            return self.canonical
        else:
            return self

    def display_str(self)->str:
        if self.id and self.name:
            return f'{self.id} [{self.name}]'
        else:
            return self.id


@dataclass
class Item:
    id: str
    categories: List[Category]


    def display(self,primary:Category)-> List[str]:
        """Unalias, dedup and sort for display."""
        if not self.categories:
            return []

        def unalias(secs:Iterator[Category])->Iterator[Category]:
            return map(lambda c: c.unalias(), secs) 

        def de_prim(secs:Iterator[Category])->Iterator[Category]:
            return filter(lambda c: c.id != primary.id, secs)

        def to_display(secs:List[Category])->List[str] :  
            return list(map(lambda c: c.display_str(), secs) )

        de_primaried = set(de_prim(unalias(iter(self.categories))))
        if not de_primaried:
            return []    
        return sorted(to_display(de_primaried))


class DoiTest(unittest.TestCase):
    def test(self):
        primary = Category('shirt', 'Shirts', None)

        cats = [Category('snow','Snowflakes',
                         Category('frozen_water','Frozen Water',None) ),
                Category('t-shirt','Tee Shirts', primary),
                Category('cheese','Yummy Cheese',None)]
        item = Item( 'ItemX', cats)
        self.assertEqual( item.display(primary) , ['cheese [Yummy Cheese]', 'frozen_water [Frozen Water]'])
Теги:
mypy

1 ответ

1
Лучший ответ

Разбивая биты mypy, похоже, что это эффективно то, что вы делаете?

def display(self, primary):
    return sorted(
        map(
            lambda c: c.display_str(), 
            set(
                filter(
                    lambda c: c.id != primary.id, 
                    map(
                        lambda c: c.unalias(), 
                        self.categories
                    )
                )
            )
        )
    )

Если нет причин, по которым вы хотите, чтобы categories имели значение None, я бы инициализировал его в пустой список. Поскольку de_primaried всегда будет действительным аргументом для сопоставления, даже если он пуст, нет необходимости проверять его и вручную возвращать пустой список.

Возможно, вы захотите рассмотреть вопрос о создании возвращаемого значения в нескольких вложенных циклах для удобства чтения (одноразовые функции там, определенно, не подходят, на мой взгляд, особенно учитывая дополнительный тип беспорядка). Кроме того, вполне возможно, что я что-то упустил, но, похоже, есть несколько ненужных запросов list() и iter().

  • 0
    Да, именно это я и собираюсь сделать.
  • 0
    Я хотел бы знать, как сделать эти ненужные вызовы list () и iter () ненужными даже при проверке mypy.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню