Python上下文对象更好地使用字典或属性?

时间:2014-11-11 00:13:09

标签: python oop

在我的Python应用程序中,我需要创建一个简单的RequestContext对象,其中包含要发送的实际请求,以及有关请求的其他一些元数据,例如: index,id,source等。此外,可能会添加更多元数据。

我可以想到两种方法:

选项1:RequestContext的属性:

class RequestContext(object):
  def __init__(self, request, index=0, source=None):
    self.request = request
    self.index = index
    self.source = source
    ...

选项2:RequestContext中的字典:

class RequestContext(object):
  def __init__(self, request):
    self.request = request
    self.context_info = {}

然后用户可以添加他们想要的任何上下文信息。

我个人喜欢通过属性访问值,因为您有一组您知道的预定义属性。

另一方面,字典允许客户端代码(由我拥有)添加更多元数据,而无需更新RequestContext对象定义。

那么哪个在易用性和添加更多元数据方面会更好?我还应该考虑其他陷阱或考虑因素吗?

1 个答案:

答案 0 :(得分:1)

首先,你似乎在误解中运作:

  

另一方面,字典允许客户端代码(由我拥有)添加更多元数据,而无需更新RequestContext对象定义。

您不必更新类定义以添加新属性。 (您可以强制该类以各种方式拥有一组固定的属性 - 例如,使用__slots__。但如果您不执行任何操作,则可以添加动态的新属性。)例如:

>>> class C(object):
...     def __init__(self, x):
...         self.x = x
>>> c = C(10)
>>> c.y = 20
>>> print(c.x, c.y)
10 20

事实上,如果你看一下封面,属性(默认情况下)存储在一个名为__dict__的完全正常的字典中:

>>> print(c.__dict__)
{'x': 10, 'y': 20}

那么,使用属性之间的区别,只是添加字典属性和使用该字典的成员(或者,继承或委托给dict)?

实际上,它与使用单独变量与顶级单个词典之间的差异相同。

查看它的一种方法是名称 - 值对是数据,还是名称是程序的一部分,只有值是数据。在前一种情况下,你想要一个字典;在后一种情况下,您需要单独的变量。

或者,您可以询问名称的动态程度。如果有一组开放式的值,其名称仅在运行时已知,那么您需要一个dict。如果有一组固定的值,其名称已硬编码到源中,则需要属性。

最后,只要问问自己,如果你使用属性,你必须经常使用getattrsetattr。如果答案是"经常",你想要一个字典;如果它"从不",你想要属性。

在许多现实应用中,它并不完全清楚,因为你介于两者之间。有时候,重新思考你的设计可以使它清楚地显示出一个或另一个,但有时事情本身就是一种动态的#34;。在这种情况下,你必须进行判断调用:决定你最接近的两种情况中的哪一种,并将代码视为真实情况。

可能值得查看一些与您类似的真​​实开源应用程序。例如,您正在处理有关某种请求的元数据。也许看看请求和pycurl如何处理类似于元数据的HTTP信息,比如标题和状态行。或者看看QuodLibet和MusicBrainz Picard如何处理不同域中的元数据,音乐文件。等等。