我应该使用课程还是字典?

dea*_*mon 85 python oop dictionary class

我有一个只包含字段而没有方法的类,如下所示:

class Request(object):

    def __init__(self, environ):
        self.environ = environ
        self.request_method = environ.get('REQUEST_METHOD', None)
        self.url_scheme = environ.get('wsgi.url_scheme', None)
        self.request_uri = wsgiref.util.request_uri(environ)
        self.path = environ.get('PATH_INFO', None)
        # ...
Run Code Online (Sandbox Code Playgroud)

这很容易被翻译成一个字典.该课程对于未来的添加更加灵活,可以快速使用__slots__.那么使用dict会有好处吗?一个dict会比一个班级快吗?比带插槽的课程更快?

Kat*_*iel 39

除非您需要类的额外机制,否则请使用字典.您还可以使用namedtuple混合方法:

>>> from collections import namedtuple
>>> request = namedtuple("Request", "environ request_method url_scheme")
>>> request
<class '__main__.Request'>
>>> request.environ = "foo"
>>> request.environ
'foo'
Run Code Online (Sandbox Code Playgroud)

这里的性能差异很小,但如果字典不快,我会感到惊讶.

  • "这里的表现差异将是**最小**,但如果字典不是**显着**更快,我会感到惊讶." 这不计算.:) (11认同)
  • @mipadi:这是真的。现在已修复:p (2认同)

Bru*_*ong 36

python 中的一个类下面的一个字典.你确实得到了类行为的一些开销,但如果没有分析器,你将无法注意到它.在这种情况下,我相信你会受益于这个课程,因为:

  • 你所有的逻辑都存在于一个功能中
  • 它很容易更新并保持封装状态
  • 如果以后更改任何内容,则可以轻松保持界面相同

  • +1"python中的一个类__is__下面的一个字典" (13认同)

adw*_*adw 24

你为什么要把它作为字典呢?有什么好处?如果您以后想要添加一些代码会发生什么?你的__init__代码会在哪里?

类用于捆绑相关数据(通常是代码).

字典用于存储键值关系,其中键通常都是相同的类型,并且所有值也是一种类型.有时候,当关键/属性名称并非都是预先知道时,它们可以用于捆绑数据,但这通常表明您的设计存在问题.

保持这个课程.

  • 不能不同意你的意思:字典,集合,列表和元组都可以捆绑相关数据.绝对没有任何假设,字典的值应该或必须是相同的数据类型,恰恰相反.在许多列表和集合中,值将具有相同的类型,但这主要是因为这是我们想要一起枚举的内容.我实际上认为广泛使用类来保存数据是滥用oop; 当你想知道序列化问题时,你可以很容易地看出原因. (77认同)
  • 我已经将此标记下来,因为您应该始终默认使用更简单的数据结构.在这种情况下,字典足以达到预期目的.问题是`你的__init__代码将去哪里?`是令人担忧的.它可以说服经验不足的开发人员只使用类,因为字典中没有使用__init__方法.荒诞. (9认同)
  • 这是面向对象的编程而不是面向类的一个原因:我们处理对象。一个对象具有 2 (3) 个属性:1. 状态(成员) 2. 行为(方法)和 3. 实例可以用几个词来描述。因此,类用于将状态和行为捆绑在一起。 (4认同)

ale*_*o98 21

我认为每个人的使用对我来说太主观了,所以我只会坚持数字.

我比较了创建和更改dict中的变量所需的时间,new_style类和带槽的new_style类.

这是我用来测试它的代码(它有点乱,但它完成了工作.)

import timeit

class Foo(object):

    def __init__(self):

        self.foo1 = 'test'
        self.foo2 = 'test'
        self.foo3 = 'test'

def create_dict():

    foo_dict = {}
    foo_dict['foo1'] = 'test'
    foo_dict['foo2'] = 'test'
    foo_dict['foo3'] = 'test'

    return foo_dict

class Bar(object):
    __slots__ = ['foo1', 'foo2', 'foo3']

    def __init__(self):

        self.foo1 = 'test'
        self.foo2 = 'test'
        self.foo3 = 'test'

tmit = timeit.timeit

print 'Creating...\n'
print 'Dict: ' + str(tmit('create_dict()', 'from __main__ import create_dict'))
print 'Class: ' + str(tmit('Foo()', 'from __main__ import Foo'))
print 'Class with slots: ' + str(tmit('Bar()', 'from __main__ import Bar'))

print '\nChanging a variable...\n'

print 'Dict: ' + str((tmit('create_dict()[\'foo3\'] = "Changed"', 'from __main__ import create_dict') - tmit('create_dict()', 'from __main__ import create_dict')))
print 'Class: ' + str((tmit('Foo().foo3 = "Changed"', 'from __main__ import Foo') - tmit('Foo()', 'from __main__ import Foo')))
print 'Class with slots: ' + str((tmit('Bar().foo3 = "Changed"', 'from __main__ import Bar') - tmit('Bar()', 'from __main__ import Bar')))
Run Code Online (Sandbox Code Playgroud)

这是输出......

创建...

Dict: 0.817466186345
Class: 1.60829183597
Class_with_slots: 1.28776730003
Run Code Online (Sandbox Code Playgroud)

改变变量......

Dict: 0.0735140918748
Class: 0.111714198313
Class_with_slots: 0.10618612142
Run Code Online (Sandbox Code Playgroud)

所以,如果你只是存储变量,你需要速度,并且它不需要你做很多计算,我建议使用dict(你总是可以创建一个看起来像方法的函数).但是,如果你真的需要课程,请记住 - 总是使用__ slots __.

注意:

我测试的"类"有两种 new_style和old_style类.事实证明,old_style类的创建速度更快,但修改速度较慢(如果你在紧密的循环中创建了很多类,则不是很多但很重要(提示:你做错了)).

此外,创建和更改变量的时间可能会因您的计算机而异,因为我的计算机已经过时且速度很慢 确保您自己测试以查看"真实"结果.

编辑:

我后来测试了namedtuple:我无法修改它,但创建10000个样本(或类似的东西)需要1.4秒,所以字典确实是最快的.

如果我更改dict函数以包含键和值并返回dict而不是包含dict的变量,当我创建它时它给我0.65而不是0.8秒.

class Foo(dict):
    pass
Run Code Online (Sandbox Code Playgroud)

创建就像一个带槽的类,更改变量是最慢的(0.17秒),所以不要使用这些类.去一个字典(速度)或从对象派生的类('syntax candy')


jay*_*del 11

我同意@adw.我永远不会用字典表示"对象"(在OO意义上).字典聚合名称/值对.类表示对象.我已经看到了用字典表示对象的代码,并且不清楚事物的实际形状是什么.当某些名称/值不存在时会发生什么?是什么限制了客户完全放入任何东西.或者试图获得任何东西.应始终明确定义物体的形状.

使用Python时,重要的是建立纪律,因为语言允许作者用很多方式射击他/她自己.

  • SO上的答案按投票排序,具有相同投票数的答案是随机排序的.所以请通过"最后一张海报"澄清你的意思. (8认同)
  • 你怎么知道只有字段和没有功能的东西是OO意义上的"对象"? (3认同)

Sti*_*gma 5

我会推荐一个课程,因为这是一个涉及请求的各种信息.如果一个人使用字典,我希望存储的数据本质上更相似.我倾向于遵循的一个指导原则是,如果我想循环遍历整个key-> value对并​​执行某些操作,我会使用字典.否则,数据显然具有比基本键 - >值映射更多的结构,这意味着类可能是更好的选择.

因此,坚持上课.

  • 我完全不同意.没有理由限制字典的使用来迭代.他们是为了维护映射. (2认同)