在Python中优先选择字典而不是对象

2024-09-29 23:28:18 发布

您现在位置:Python中文网/ 问答频道 /正文

在Python中使用字典而不是对象(反之亦然)是否有好处?在

我正在工作的项目目前有很多地方使用字典,而我通常会在这些地方创建对象。在我看来,对象提供了更多的结构,允许像pylint这样的程序进行更好的程序员错误检查,但是很难解释为什么我会使用对象而不是dict

对于模拟示例,一个模块创建小部件并包含如下方法:

def create(self, propertyA, propertyB=55, propertyC="default", 
           propertyD=None, propertyE=None, propertyF=None, propertyG=None,
           propertyH=None, propertyI=None):

该方法将通过创建字典并按如下方式传入来调用:

^{pr2}$

当我看到这一点时,我发现这些属性中的每一个都描述了一个“Widget”,并希望执行以下操作:

class Widget(object):
    """Represents a widget."""

    def __init__(self, propertyA, **kwargs):
        """Initialize a Widget.

        :param propertyA: The name of the widget.
        :param kwargs: Additional properties may be specified (see below).
        :returns: None

        """
        self.propertyA = propertyA
        self.propertyB = kwargs.get("propertyB", 55)
        self.propertyC = kwargs.get("propertyC", "default")
        self.propertyD = kwargs.get("propertyD", None)
        self.propertyE = kwargs.get("propertyE", None)
        self.propertyF = kwargs.get("propertyF", None)

然后更新create()方法如下所示:

def create(self, widget):

结果是这样的:

widget_client = WidgetClient()
widget = Widget(propertyA="my_widget")
widget.propertyB = 10
...
widget_client.create(widget)

在我看来,这显然更好,但我过去错了,我想不出该怎么解释自己。当然,我仍然在使用**kwargs,这可以通过将Widget分解成更小的组件/相关部分和创建更多的对象等来避免,但我觉得这是一个很好的“第一步”。这有什么意义吗?在

字典的好处

  1. 更快和/或更高效的内存

字典的缺点

  1. 无法使用静态代码检查程序捕获某些错误
  2. 所有窗口小部件属性的完整列表可能永远不会出现或为人所知

对象的好处

  1. 确切地知道“小部件”是由什么组成的
  2. 使用静态代码检查程序可能会捕获错误(尽管使用**魔法可以防止某些错误)

缺点:

  1. 速度较慢和/或内存效率较低

这似乎是一个愚蠢的问题,但为什么要用字典可以处理的对象呢?在


Tags: 对象方法selfnoneget字典部件def
3条回答

不,用字典代替对象没有好处-对象中的数据通常存储在字典中。在

使用对象而不是字典可能有好处。参见: http://docs.python.org/reference/datamodel.html#slots

可以用namedtuple很好地实现这一点。例如,可以使用默认值创建名为dtuple的小部件:

>>> from collections import namedtuple
>>> _Widget = namedtuple("Widget", "propertyA propertyB propertyC propertyD propertyE propertyF propertyG propertyH propertyI")
>>> DefaultWidget = _Widget(None, 55, "Default", None, None, None, None, None, None)
>>> DefaultWidget
Widget(propertyA=None, propertyB=55, propertyC='Default', propertyD=None, propertyE=None, propertyF=None, propertyG=None, propertyH=None, propertyI=None)

然后,您可以使用一个名为Widget的函数初始化属性:

^{pr2}$

然后你可以这样使用它:

>>> Widget("test", propertyE=17)
Widget(propertyA='test', propertyB=55, propertyC='Default', propertyD=None, propertyE=17, propertyF=None, propertyG=None, propertyH=None, propertyI=None)

请注意,如果您试图省略所需的属性a:

>>> Widget()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Widget() takes exactly 1 argument (0 given)

或者如果你给了一个不存在的属性:

>>> Widget("test", propertyZ="test2")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in Widget
  File "<string>", line 32, in _replace
ValueError: Got unexpected field names: ['propertyZ']

它处理得很好。我认为使用namedtuple可以消除你使用字典的缺点。在

使用任何内置的数据类型都会给您带来一些功能上的优势,而且它的行为也为其他程序员所熟知。字典给了你一个充满了内置方法的拳头,没有人会怀疑它是否是iterable。在

这只是一个优势。我不是说你应该总是使用字典而不是声明你自己的对象。(当然,您的新对象可以继承类似字典的行为),但您不必总是选择创建一个新对象,而一个更简单的存储机制可能会做到这一点。以理解为指导,这将取决于Widget是否有任何特殊的行为或属性。在

相关问题 更多 >

    热门问题