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

Python上下文对象更好地使用字典或属性?,python,oop,Python,Oop,在我的Python应用程序中,我需要创建一个简单的RequestContext对象,其中包含要发送的实际请求,以及关于请求的一些其他元数据,例如索引、id、源等。此外,可能还会添加更多元数据 我可以想出两种方法: 选项1:RequestContext的属性: 选项2:RequestContext中的字典: 然后用户可以添加他们想要的任何上下文信息 我个人喜欢通过属性访问值,因为您有一组预定义的属性,您知道这些属性就在那里 另一方面,字典允许客户端代码(由我拥有)添加更多元数据,而无需更新Requ

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

我可以想出两种方法:

选项1:RequestContext的属性: 选项2:RequestContext中的字典: 然后用户可以添加他们想要的任何上下文信息

我个人喜欢通过属性访问值,因为您有一组预定义的属性,您知道这些属性就在那里

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


那么,在易用性和添加更多元数据的易用性方面,哪一个更好呢?我还应该考虑其他陷阱或考虑事项吗?

首先,您似乎在误解中操作:

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

您不必更新类定义来添加新属性。(您可以通过各种方式强制类具有一组固定的属性,例如,通过使用
\uuuuuu插槽\uuuuu
。但如果您不这样做,您可以动态添加新属性。)例如:

>>> class C(object):
...     def __init__(self, x):
...         self.x = x
>>> c = C(10)
>>> c.y = 20
>>> print(c.x, c.y)
10 20
事实上,如果你在封面下查看,属性(默认情况下)存储在一个完全正常的字典中,名为
\uuu dict\uu

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

那么,使用属性与仅仅添加字典属性和使用字典成员(或者从dict继承或委托给dict)之间有什么区别呢

实际上,这与在顶层使用单独变量和单个dict的区别是一样的

查看它的一种方法是,名称-值对是否是数据,或者名称是否是程序的一部分,并且只有值是数据。在前一种情况下,您需要一个dict;在后一种情况下,您需要单独的变量

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

最后,问问自己,如果使用属性,您需要多久使用一次
getattr
setattr
。如果答案是“频繁”,你需要一个口述;如果是“从不”,则需要属性

在许多现实生活中的应用程序中,这并不完全清楚,因为你介于两者之间。有时候,重新思考你的设计可以让它变得清晰,但有时候事情本身就是“某种动态的”。在这种情况下,你必须做出判断:决定你最接近的两个案例中的哪一个,并像真实案例那样编码


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

谢谢你的建议和考虑。我认为在我的情况下,我会使用属性,因为名称根本不是动态的。客户端通常只是从一组预定义的属性中读取数据。
>>> class C(object):
...     def __init__(self, x):
...         self.x = x
>>> c = C(10)
>>> c.y = 20
>>> print(c.x, c.y)
10 20
>>> print(c.__dict__)
{'x': 10, 'y': 20}