Как избежать типа параметра в имени функции? - PullRequest
0 голосов
/ 11 мая 2018

У меня есть функция foo, которая принимает параметр stuff Материал может быть чем-то в базе данных, и я хотел бы создать функцию, которая принимает stuff_id, получить stuff из БД, выполнитьfoo.

Вот моя попытка ее решить: 1 / Создать вторую функцию с суффиксом from_stuff_id

def foo(stuff):
    do something

def foo_from_stuff_id(stuff_id):
    stuff = get_stuff(stuff_id)
    foo(stuff)

2 / Изменить первую функцию

def foo(stuff=None, stuff_id=None):
    if stuff_id:
        stuff = get_stuff(stuff_id)
    do something

Мне не нравятся оба пути.Какой самый питонный способ сделать это?

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Это в основном зависит от того, как вы определили все эти функции.Если вы импортируете get_stuff из другого модуля, второй подход более Pythonic, потому что с точки зрения ООП вы создаете функции для одной конкретной цели, и в этом случае, когда вы уже определили get_stuff, вам не нужночтобы вызвать его в другой функции.

Если get_stuff не определено в другом модуле, то это зависит от того, используете ли вы классы или нет.Если вы используете класс и хотите использовать все эти модули вместе, вы можете использовать метод для доступа к базе данных или для подключения к ней и использовать этот метод в других методах, таких как foo.

Пример:

from some module import get_stuff

MyClass:
    def __init__(self, *args, **kwargs):
       # ...
       self.stuff_id = kwargs['stuff_id']         

    def foo(self):
        stuff = get_stuff(self.stuff_id)
        # do stuff

Или, если функциональность foo зависит от существования stuff, вы можете иметь глобальный stuff и просто проверить его правильность:

MyClass:
    def __init__(self, *args, **kwargs):
       # ...
       _stuff_id = kwargs['stuff_id']
       self.stuff = get_stuff(_stuff_id)  # can return None          

    def foo(self):
        if self.stuff:      
            # do stuff
        else:
            # do other stuff

Илидругой аккуратный шаблон проектирования для таких ситуаций может использовать функцию диспетчера (или метод в классе), который делегирует выполнение различным функциям в зависимости от состояния stuff.

def delegator(stff, stuff_id):
    if stuff:  # or other condition 
        foo(stuff)
    else:
        get_stuff(stuff_id)
0 голосов
/ 11 мая 2018

Я не большой поклонник перегрузки типов в Python, но это один из случаев, когда я мог бы пойти на это, если действительно есть необходимость:

def foo(stuff):
    if isinstance(stuff, int):
        stuff = get_stuff(stuff)
    ...

С аннотациями типа это будет выглядеть так:

def foo(stuff: Union[int, Stuff]):
    if isinstance(stuff, int):
        stuff = get_stuff(stuff)
    ...
0 голосов
/ 11 мая 2018

Предположим, foo - это главный компонент вашего приложения, ваш первый путь.У каждой функции должно быть свое назначение.В тот момент, когда вы объединяете несколько целей в одну функцию, вы можете легко потеряться в длинных потоках кода.

Если, однако, какая-то другая функция также может предоставить материал , тогда переходите ксекунда.

Единственное, что я хотел бы добавить, это убедиться, что вы добавляете строки документации ( PEP-257 ) к каждой функции, чтобы объяснить словами ее роль.При необходимости вы также можете добавить комментарии к своему коду.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...