17

我对 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获取配置文件中每个部分的配置设置。如果有人能想出另一种方法,那就太好了!谢谢!

4

2 回答 2

14

我肯定会在__init__. 不这样做会导致复杂性增加和潜在的意外副作用。

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

访问控制:

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

另一方面,如果访问更复杂,或者访问变量的成本很高,则应该使用函数调用(遵循命名准则),例如 get_foo() 和 set_foo()。如果过去的行为允许通过属性进行访问,则不要将新的访问器函数绑定到该属性。任何仍试图通过旧方法访问变量的代码都应该明显中断,以便让他们意识到复杂性的变化。

来自 PEP8

对于简单的公共数据属性,最好只公开属性名称,而不需要复杂的访问器/修改器方法。请记住,如果您发现简单的数据属性需要增加功能行为,Python 提供了一条通往未来增强的简单途径。在这种情况下,使用属性将功能实现隐藏在简单的数据属性访问语法之后。

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

注意 2:尽量保持功能行为无副作用,尽管缓存等副作用通常没问题。

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

Python isn't java/C#, and it has very strong ideas about how code should look and be written. If you are coding in python, it makes sense to make it look and feel like python. Other people will be able to understand your code more easily and you'll be able to understand other python code better as well.

于 2012-05-01T11:50:23.580 回答
6

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

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

如果您担心某些配置值并不总是需要并且计算起来很昂贵(我猜这就是为什么您有 get_info(),允许延迟执行),那么我会考虑将该配置子集重构为第二类或引入返回值的属性或函数。

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

一旦你对实例变量进行了封装,你就可以选择做更多的事情,而不仅仅是抛出一个NameError异常——你也许可以调用get_info()你自己,或者抛出一个自定义异常。


1.你不能用 Python 提供 100% 的封装,因为由前导双下划线表示的私有实例变量只有按照约定是私有的

于 2012-05-01T11:28:37.570 回答