以正确的方式编写大型python类

时间:2013-03-09 13:43:48

标签: python class coding-style

编写一个python类,它具有不同的函数来获取数据和解析数据;什么是最正确的方法? 你可以编写它,这样你就可以逐个填充self.data,然后运行解析函数来填充self.parsed_data ....或者编写接受self.data并返回self.parsed_data的函数是正确的。 ?

以下示例。 MyClass1填充self.variables,MyClass2将它们作为参数。 我认为MyClass2“最”正确。

那么,什么是正确的?为什么?我一直试图决定这两种编码风格中的哪一种。但我想知道哪些被认为是最佳做法。

class MyClass1(object):
    def __init__(self):
        self.raw_data = None

    def _parse_data(self):
        # This is a fairly complex function xml/json parser
        raw_data = self.raw_data
        data = raw_data  #  Much for is done to do something with raw_data
        cache.set('cache_key', data, 600)  # Cache for 10 minutes
        return data

    def _populate_data(self):
        # This function grabs data from an external source
        self.raw_data = 'some raw data, xml, json or alike..'

    def get_parsed_data(self):
        cached_data = cache.get('cache_key')
        if cached_data:
            return cached_data
        else:
            self._populate_data()
            return self._parse_data()

mc1 = MyClass1()
print mc1.get_parsed_data()


class MyClass2(object):
    def _parse_data(self, raw_data):
        # This is a fairly complex function xml/json parser
        data = raw_data  # After some complicated work of parsing raw_data
        cache.set('cache_key', data, 600)  # Cache for 10 minutes
        return data

    def _get_data(self):
        # This function grabs data from an external source
        return 'some raw data, xml, json or alike..'

    def get_parsed_data(self):
        cached_data = cache.get('cache_key')
        if cached_data:
            return cached_data
        else:
            return self._populate_data(self._get_data())

mc2 = MyClass2()
print mc1.get_parsed_data()

4 个答案:

答案 0 :(得分:2)

最后归结为个人偏好。但是IMO,最好只有一个名为parse_data的模块级函数,它接收原始数据,做大量工作并返回解析后的数据。我假设您的缓存键以某种方式从原始数据派生,这意味着parse_data函数也可以实现您的缓存逻辑。

我更喜欢一个功能而不是一个完整的类的原因是简单。如果你想拥有一个提供从原始数据中提取的数据字段的类,那么对象的用户可以执行类似obj.some_attr的操作,而不必查看某些较低级别的数据结构(例如JSON,XML, Python dict等),我会创建一个简单的“值对象”类,它只包含数据字段,并且没有解析逻辑,并且前面提到的parse_data函数返回一个这样的实例class(基本上充当数据类的工厂函数)。这导致更少的状态,更简单的对象和没有懒惰,使您的代码更容易推理。

这也可以使单元测试此类的使用者变得更容易,因为在这些测试中,您可以简单地使用字段实例化数据对象,而不必提供大量的测试原始数据。

答案 1 :(得分:1)

对我来说,最正确的类是用户理解并使用的类,尽可能少的错误。

当我看第2课时,我会问自己如何使用它......

mc2 = MyClass2()
print mc1.get_parsed_data()

我只想

print get_parsed_data()

有时候not write classes更好。

答案 2 :(得分:0)

第二种方式更可取,因为(如果我理解正确的话)效率和结果相同,但避免使用原始数据的实例成员。通常,您希望减少存储在对象中的数据量,因为每个额外属性意味着更加担心一段时间内的一致性。

换句话说,它“更具功能性”。

答案 3 :(得分:0)

以这种方式思考这个问题:如果您将这个逻辑组合成一个长方法,而不是使用两个方法,那么在解析原始数据后,您是否会跟踪它?如果答案是肯定的,那么将它存储为属性是有意义的。但如果您在此之后不再关心它,请选择第二种形式。将逻辑的一部分分解为“辅助”子程序应该最好避免对其他方法可能需要关注的类进行更改。