Как обрабатывать флаги ключевых слов со значениями по умолчанию в пользовательских классах? - PullRequest
1 голос
/ 19 марта 2020

У меня есть пользовательские классы, которые используют много флагов ключевых слов, которые могут быть любого типа данных.

class Example():
    def __init__(self, main_arg, para1 = True, para2 = False, para3 = 2, para4 = 0):
        if para1 and para2:
            a = para3
        elif para1:
            a = para4
        #and so on

Так как существует много параметров и намного больше логических c (и они не имеют красивых имен para #, как в этом примере), я решил использовать ** kwargs

class Example():
    def __init__(self, main_arg, **extras):
        if extras["para1"] and extras["para2"]:
            a = extras["para3"]
        elif extras["para1"]:
            a = extras["para4"]
        #and so on

Однако для этого требуется, чтобы пользователь класса Example вводил КАЖДЫЙ аргумент в дополнительные функции, и, следовательно, параметры по умолчанию отсутствуют , Я справился с этим, выполнив быструю проверку в функции __init__ и заполнив параметры по умолчанию.

class Example():
    def __init__(self, main_arg, **extras):

        extras_keys_true = ["para1"]
        extras_keys_false = ["para2"]
        extras_keys_zero = ["para4"]
        extras_keys_two = ["para3"]

        for key in extras_keys_true:
            if key not in extras:
                extras[key] = True

        for key in extras_keys_false:
            if key not in extras:
                extras[key] = False

        for key in extras_keys_zero:
            if key not in extras:
                extras[key] = 0

        for key in extras_keys_two:
            if key not in extras:
                extras[key] = 2

        if extras["para1"] and extras["para2"]:
            a = extras["para3"]
        elif extras["para1"]:
            a = extras["para4"]
        #and so on

Это выглядит уродливо и неэффективно, но работает, пока я обновляю значения, которые ожидаю в extra_keys_..., а также добавьте еще одну проверку для каждого нового значения по умолчанию, которое мне нужно.

У меня вопрос, есть ли лучший способ справиться с этой ситуацией.

Ответы [ 2 ]

1 голос
/ 19 марта 2020

Я думаю, что вы должны сделать какой-то дизайн программного обеспечения с помощью логики c и шаблонов проектирования:

Упрощение логики c может помочь: если это первый случай, он все равно перезаписывается здесь , Так не будет, но, может быть, logi c может быть проще.

    if extras["para1"] and extras["para2"]:
        a = extras["para3"]
    elif extras["para1"]:
        a = extras["para4"]

Или вы группируете параметры в логические группы, например, вложенные dicts или json.

Example("x", {"kwargs1": {"kw":arg, ...}, "kwargs2":{}...})

Или, что может быть лучше: с наследованием и полиморфизмом вы можете разделить логи c и повторно использовать общий код, как сейчас. Это основная причина его использования.

class AbstractExample:
    def __init__(self, mainArgument, a=None, b="123", c="path|to|"):
        self.setup(a)
        self.do(b)
        self.save_at(c)

    def setup(self,a):
        self.a =

    def do(self, b):
        self.value = b(self.a)

    def save_at(path):
        with open (path) as something:
            something.save(self.value)              


class ExampleA(AbstractExample):
    def __init__(self, *args, extra_arg="special", **kwargs):
        super().__init__(*args,**kwargs)
        print(extra_arg)

    def save_at(path):
        # not saving
        pass


class ExampleB(AbstractExample):
    def __init__(self, *args, anything_else="also_important", **kwargs):
        super().__init__(*args,**kwargs)
        print(anything_else)

    def do(b):
        # do something that is special in for cases like this

    def save_at(path):
        # these methods override the base class behavior
        non_overloading_method_to_do_this()

    def non_overloading_method_to_do_this():

С несколькими уровнями наследования вы можете разделить каждый случай, который вам нужен, и вы увидите, что для этого гораздо проще думать и отлаживать это, чем логику c ты сделал. Он вызовет все методы в init в зависимости от объекта, который вы создаете:

a = ExampleA(..., extra_arg="special", ...)
b = ExampleB(..., anything_else="also_important", b="1""...)
0 голосов
/ 19 марта 2020

Я не уверен, что полностью понимаю проблему, но, возможно, вы можете обойти ее, используя get() метод словаря. Этот метод дает вам значение предоставленного ключа, если он находится в словаре. Если нет, вы можете присвоить ему значение по умолчанию. Например, код может выглядеть следующим образом:

param = extras.get('key', True)

В этом случае, если 'key' отсутствует в extras, extras['key'] будет автоматически установлено на True. Вы можете сделать то же самое тогда для каждого параметра.

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