Входные переменные метода класса - PullRequest
0 голосов
/ 11 декабря 2018

Часто, когда я создаю классы на Python (и других языках), я пытаюсь решить, какой из них лучше: (a) использовать переменные экземпляра в функциях моего метода или (b) перечислить входные переменные в определении функции.

(а)

    class ClassA(object):
        def __init__(self, a):
            self.variable_a = a

        def square_a(self):
            return self.variable_a ** 2

(б)

   class ClassB(object):
        def __init__(self, b):
            self.variable_b = b

        def square_b(self, input_var):
            return input_var ** 2

Эти примеры очень просты и очевидны, но они подчеркивают то, что я нахожу запутанным в отношении того, что лучшеидея.Кроме того, запрещено ли устанавливать переменную экземпляра вне метода __init__?Например:

   class ClassC(object):
        def __init__(self, c):
            self.variable_c = c

        def square_c(self):
            self.square_of_c = self.variable_c ** 2

РЕДАКТИРОВАТЬ : Я понимаю несколько расплывчатую природу этого вопроса, но я задал его, потому что трудно понять, что люди ожидают увидеть в исходном коде, который янаписать, скажем, для совместных проектов.Если один или несколько примеров, которые я привел, являются анти-паттерном, я думал, что этот вопрос даст мне полезную информацию.

Из PEP 20:

There should be one-- and preferably only one --obvious way to do it.

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

В этом примере (b) не очень полезна в качестве функции-члена.Это может быть просто бесплатная функция:

def square(input_var):
    return input_var ** 2

Возможно, это лучший интерфейс, так как его можно использовать в любом контексте, а не только из экземпляра ClassB.

Как правило, я бы использовал (а), если бы знал, что self.variable_a - единственный вход, который необходим функции.Если я хочу, чтобы это работало с чем-либо, и это ни от чего не зависело в классе, я бы сделал это бесплатной функцией.Если я хочу, чтобы он работал с чем-либо, но он зависит от некоторого состояния класса, тогда сделайте его членом, который принимает входные данные в качестве параметра.Например, что если ClassA содержит и variable_a, и variable_b?Вы не можете использовать square_a для изменения variable_b, что может или не может быть желательным в зависимости от фактического варианта использования.

Кроме того, запрещено ли устанавливать переменную экземпляра вне init метод?

Нет, но, как правило, рекомендуется убедиться, что все члены инициализированы где-то во время создания экземпляра класса.Даже если вы просто инициализируете своих членов на None.Гораздо проще проверить, является ли переменная-член None, чем пытаться определить, определена ли она.

РЕДАКТИРОВАТЬ: Еще несколько примеров:

# Here a free function makes the most sense because the operation is 'pure'
# i.e. it has no side effects and requires no state besides its input arguments
def square(value):
    return value ** 2

class LoggedCalculator(object):
    def __init__(self, logger):
        self.__logger = logger

    # (a) makes more sense here because it depends on class state and doesn't need to change
    # its behavior by taking in some parameter
    def get_logger(self):
        return self.__logger

    # (b) makes more sense here because we rely on a mixture of class state and some other input
    def square(self, value):
        result = square(value) # Re-use free function above
        self.__logger.info('{}^2 = {}'.format(value, result))
        return result

calc = LoggedCalculator(logging.getLogger())
calc.square(4)  # This requires an instance of LoggedCalculator
square(2)       # This can be called anywhere, even if you don't have a logger available
0 голосов
/ 11 декабря 2018

Ваш вопрос действительно расплывчатый и поэтому трудно ответить.Все классы, кажется, имеют правильный синтаксис.

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

б) меня интересует, для чего вы используете переменную_b, поскольку она никогда не использовалась на самом деле.Но я полагаю, это из-за упрощения.
Также вы можете рассмотреть возможность сделать square_b статическим методом , так как он не использует никаких атрибутов объекта.(никогда не вызывает self)

class ClassB(object):
    def __init__(self, b):
        self.variable_b = b

    @staticmethod
    def square_b(input_var):
        return input_var ** 2

Вариант c) также допустим с точки зрения синтаксиса, но некоторые могут посчитать это плохой практикой.На самом деле это вопрос вкуса, но многие книги и веб-сайты советуют вам объявлять переменные в методе init .

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