В этом примере (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