什么是基于类实例化程序的pythonic方法

时间:2014-01-31 11:46:40

标签: python

我有以下程序:

class MyClass(object):
    def __init__(self):
        pass
    def hello(self):
        print ("hello")

if __name__ == "__main__":
    a = MyClass()
    a.hello()

它也可以作为

启动
class MyClass(object):
    def __init__(self):
        self.hello()
    def hello(self):
        print ("hello")

if __name__ == "__main__":
    MyClass()

是否有理由偏爱另一种风格,蟒蛇风格(个人喜好之外)?换句话说:在__init__中处理程序的一般流程和逻辑与在类之外处理流程是否存在优势/劣势?

该代码旨在作为独立脚本运行,与上面的示例非常相似,只是更复杂。

4 个答案:

答案 0 :(得分:1)

你总是可以问自己:如果我实例化这个类的100个实例,这仍然是我想要的行为吗?

将此对象应该执行的所有内容加载到单个方法(例如 init (self)中,以使主方法尽可能短,这很诱人。只要这个保留在你的私人脚本中,没有必要优先选择其中一个。

但是,一旦代码被共享,或者类被另一个脚本导入,您可以通过使 init ()仅执行一些必要的初始化命令来提高可重用性。

答案 1 :(得分:1)

我发明了另一个例子,显示了以第二种方式开设课程的动机。显然,这对它的作用大大过度设计。让我们假设除了你的调用之外,还有一些其他代码可以使用该类来执行除调用一个函数之外的其他操作,因此这个复杂的接口是合理的。

class MyClass(object):
    def __init__(self):
        self.get_config()
        self.validate_config()
        self.hello()
    def get_config(self):
        self.message = "hello"
    def validate_config(self):
        # I'm not claiming this is good practice, just
        # an example of multiple methods that share state
        if not self.message:
            raise Exception()
    def hello(self):
        print(self.message)

if __name__ == "__main__":
    MyClass()

那么我们在这里有什么?基本上你正在使用对MyClass的调用而不是为了创建一个对象(虽然它确实这样做而你丢弃它),但是为了执行对象的__init__方法。当然,它有效,但它不是“自然的”。自然的是,如果你想运行“某些东西”,你可以调用一个包含这些东西的函数。你并不特别想要它返回一些你甚至不关心的对象。如果东西需要维持一些状态来完成它的工作,那么函数可以处理它,你不需要它来向你显示最后的状态:

class MyClass(object):
    def __init__(self):
        self.get_config()
        self.validate_config()
    def get_config(self):
        self.message = "hello"
    def validate_config(self):
        # I'm not claiming this is good practice, just
        # an example of multiple methods that share state
        if not self.message:
            raise Exception()
    def hello(self):
        print(self.message)

def main():
    MyClass().hello()

if __name__ == "__main__":
    main()

这看起来更像是你的第一个风格,而不是你的第二个风格,所以在这个意义上我更喜欢第一个风格。

拥有main函数可能会使您在某种线束下使用模块更容易一些,比如Python提示或测试工具。但是,这没有必要。如果有人想要像__name__ == '__main__'那样做,那么最坏的情况是他们可以复制该来源。

答案 2 :(得分:0)

我感谢你的例子只是为了说明你的观点,而不是因为你想要打印“你好”而需要一个班级这样做;)

文件中的if __name__ == "__main__":表明该文件也适合导入。您是否希望类在实例化时始终打印“hello”?通常,行为在方法中,__init__仅包含初始化。

答案 3 :(得分:0)

嗯,你在这里解决不同的问题。通常,创建对象的目的不是让它触发某些东西然后消失(这更像是一个函数的工作)。相反,您通常希望反对留下来并与之互动。因此,您肯定希望将对象引用保存在变量中:

obj = MyClass()

接下来,您应该考虑在创建对象时是否始终始终 。如果是这种情况,那么是的,您可能应该将其放入__init__。如果即使只是一个小案例也不是这样,那么你应该把它分开,以便能够分别进行初始化和那个动作。

你的例子显然非常简单,所以它首先没有多大意义。但通常情况下,我会将hello视为公共API,在拥有该类型的对象时我可能会调用它。另一方面,我不希望在创建对象时自动调用它。

在某些情况下,类似的内容可能会有用并且需要,但一般情况下,您更愿意明确地调用该方法。