定义实例变量时的最佳实践

时间:2012-05-01 11:15:32

标签: python variables constructor

我对Python很新,对下面的课有疑问:

class Configuration:
    def __init__(self):
        parser = SafeConfigParser()
        try:
            if parser.read(CONFIG_FILE) is None:
                raise IOError('Cannot open configuration file')
        except IOError, error:
            sys.exit(error)
        else:
            self.__parser = parser
            self.fileName = CONFIG_FILE

    def get_section(self):
        p = self.__parser
        result = []
        for s in p.sections():
            result.append('{0}'.format(s))
        return result

    def get_info(self, config_section):
        p = self.__parser
        self.section = config_section
        self.url = p.get(config_section, 'url')
        self.imgexpr = p.get(config_section, 'imgexpr')
        self.imgattr1 = p.get(config_section, 'imgattr1')
        self.imgattr2 = p.get(config_section, 'imgattr2')
        self.destination = p.get(config_section, 'destination')
        self.createzip = p.get(config_section, 'createzip')
        self.pagesnumber = p.get(config_section, 'pagesnumber')

在本例中,在另一个函数get_info中添加更多实例变量是否可以,或者最好在构造函数中定义所有实例变量?如果我在整个地方定义新的实例变量,它是不是会导致意大利面条代码?

编辑:我正在使用这个代码和一个简单的图像处理程序。通过get_section我返回配置文件中的所有部分,然后遍历它们以访问我正在抓取图像的每个网站。对于每次迭代,我调用get_section来获取配置文件中每个部分的配置设置。 如果有人能提出另一种方法,那就没事了!谢谢!

2 个答案:

答案 0 :(得分:13)

我肯定会在__init__中声明所有实例变量。不这样做会导致复杂性增加和潜在的意外副作用。

为了提供David Hall在访问方面的备用观点,这是来自Google Python style guide

  

访问控制:

     

如果访问者功能很简单,你应该使用public   变量而不是访问器函数,以避免额外的成本   Python中的函数调用。添加更多功能后,您可以使用   保持语法一致的属性

     

另一方面,如果访问更复杂,或访问成本   变量很重要,你应该使用函数调用(以下   命名准则),例如get_foo()和set_foo()。如果过去   行为允许通过属性访问,不绑定新的   访问者对财产的功能。任何仍在尝试的代码   通过旧方法访问变量应该明显地破坏它们   意识到复杂性的变化。

From PEP8

  

对于简单的公共数据属性,最好只公开   属性名称,没有复杂的访问器/ mutator方法。留在   请注意,Python提供了一条简单的未来增强途径   你会发现一个简单的数据属性需要增长功能   行为。在这种情况下,使用属性来隐藏功能   简单数据属性访问语法背后的实现。

     

注1:属性仅适用于新式类。

     

注2:尽管如此,尽量保持功能行为的副作用   缓存等副作用通常很好。

     

注3:避免使用属性计算昂贵   操作;属性表示法使调用者相信   访问(相对)便宜。

Python不是java / C#,它对代码的外观和编写有非常强烈的想法。如果你在python中编码,那么使它看起来和感觉像python是有意义的。其他人将能够更轻松地理解您的代码,并且您将能够更好地理解其他python代码。

答案 1 :(得分:6)

我倾向于在构造函数中设置所有实例变量而不是将类放在有效状态所需的函数get_info()

对于仅通过调用诸如get_info()之类的方法实例化的公共实例变量,您可以创建一个可以使用雷区的类。

如果你担心某些配置值并不总是需要并且计算成本很高(我想这就是为什么你有get_info(),允许延迟执行),那么我要么考虑重构那个子集配置到第二个类或引入properties或返回值的函数。

使用属性或获取样式函数,您可以鼓励类的使用者通过已定义的接口并改进封装 1

一旦你对实例变量进行了封装,你就可以选择做一些事情,而不仅仅是抛出一个NameError异常 - 你可以自己调用get_info(),或者抛出一个自定义异常。< / p>


1。您无法使用Python提供100%封装,因为由前导双下划线表示的私有实例变量仅按惯例隐私