在我的Python应用程序中,我需要创建一个简单的RequestContext对象,其中包含要发送的实际请求,以及有关请求的其他一些元数据,例如: index,id,source等。此外,可能会添加更多元数据。
我可以想到两种方法:
class RequestContext(object):
def __init__(self, request, index=0, source=None):
self.request = request
self.index = index
self.source = source
...
class RequestContext(object):
def __init__(self, request):
self.request = request
self.context_info = {}
然后用户可以添加他们想要的任何上下文信息。
我个人喜欢通过属性访问值,因为您有一组您知道的预定义属性。
另一方面,字典允许客户端代码(由我拥有)添加更多元数据,而无需更新RequestContext对象定义。
那么哪个在易用性和添加更多元数据方面会更好?我还应该考虑其他陷阱或考虑因素吗?
答案 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。如果有一组固定的值,其名称已硬编码到源中,则需要属性。
最后,只要问问自己,如果你使用属性,你必须经常使用getattr
和setattr
。如果答案是"经常",你想要一个字典;如果它"从不",你想要属性。
在许多现实应用中,它并不完全清楚,因为你介于两者之间。有时候,重新思考你的设计可以使它清楚地显示出一个或另一个,但有时事情本身就是一种动态的#34;。在这种情况下,你必须进行判断调用:决定你最接近的两种情况中的哪一种,并将代码视为真实情况。
可能值得查看一些与您类似的真实开源应用程序。例如,您正在处理有关某种请求的元数据。也许看看请求和pycurl如何处理类似于元数据的HTTP信息,比如标题和状态行。或者看看QuodLibet和MusicBrainz Picard如何处理不同域中的元数据,音乐文件。等等。