类方法输入变量

时间:2018-12-10 21:53:16

标签: python python-3.x oop

通常,当我使用Python(和其他语言)创建类时,我常常难以决定哪种方法更好:(a)在我的方法函数中使用实例变量,或(b)在函数定义中列出输入变量。 / p>

(a)

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

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

(b)

   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 :(得分:1)

在此示例中,(b)作为成员函数不是很有用。它也可以很容易地成为一个免费功能:

def square(input_var):
    return input_var ** 2

这可以说是一个更好的界面,因为它可以在任何上下文中使用,而不仅仅是在ClassB的实例中使用。

通常,如果我知道self.variable_a是该功能所需的唯一输入,则我会选择(a)。如果我希望它可以与任何东西一起使用并且它不依赖于类中的任何东西,则可以将其设为自由函数。如果我希望它除确实以外都可以工作,请使其依赖于某些类状态,然后使其成为将输入作为参数的成员。例如,如果ClassA同时包含variable_avariable_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

答案 1 :(得分:0)

您的问题确实很模糊,因此很难回答。所有的类似乎都有正确的语法。

但是b)对我来说比a)更有用 看来您只想返回输入变量的平方,所以我假设您一直想计算不同值的平方。如果在a)情况下这样做,则每次调用该方法之前都必须设置变量。

b)让我想知道您使用的是variable_b是什么,因为它从未真正使用过。但是我想这是出于简化的原因。 您也可以考虑将square_b设为static method,因为它不使用任何对象属性。 (从不致电self

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

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

变体c)在语法方面也有效,但有些人可能认为它是不好的做法。确实存在品味问题,但是许多书籍和网站都会建议您使用 init 方法声明变量。