当前位置: 代码迷 >> python >> 字典键的Javascript样式点表示法是非Python的吗?
  详细解决方案

字典键的Javascript样式点表示法是非Python的吗?

热度:92   发布时间:2023-07-14 09:48:46.0

我已经开始使用如下构造:

class DictObj(object):
    def __init__(self):
        self.d = {}
    def __getattr__(self, m):
        return self.d.get(m, None)
    def __setattr__(self, m, v):
        super.__setattr__(self, m, v)

更新:基于此线程,我已将DictObj实现修改为:

class dotdict(dict):
    def __getattr__(self, attr):
        return self.get(attr, None)
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

class AutoEnum(object):
    def __init__(self):
        self.counter = 0
        self.d = {}
    def __getattr__(self, c):
        if c not in self.d:
            self.d[c] = self.counter
            self.counter += 1        
        return self.d[c]

其中DictObj是可以通过点表示法访问的字典:

d = DictObj()
d.something = 'one'

我发现它比d['something']更美观。 请注意,访问未定义的键将返回None而不是引发异常,这也很好。

更新:Smashery很好,mhawke对其进行了扩展以提供更简单的解决方案。 我想知道使用dict而不是定义新字典是否有任何不良后果; 如果没有,我非常喜欢mhawke的解决方案。

AutoEnum是一个自动递增的Enum,用法如下:

CMD = AutoEnum()

cmds = {
    "peek":  CMD.PEEK,
    "look":  CMD.PEEK,
    "help":  CMD.HELP,
    "poke":  CMD.POKE,
    "modify": CMD.POKE,
}

两者都对我来说运作良好,但是我对它们感到python昧。

这些实际上是不好的构造吗?

您的DictObj示例实际上很常见。 如果您要处理“类似于对象的事物”,则对象样式的点符号访问可能是一个胜利。 它们具有固定的属性名称,仅包含在Python标识符中有效的字符。 诸如数据库行或表单提交之类的东西可以有效地存储在此类对象中,从而使代码更具可读性,而无需过多的['item access']。

实现有点受限-您无法获得dict,len(),比较,'in',迭代或不错的reprs的出色构造函数语法。 您当然可以自己实现这些东西,但是在新式类世界中,只需将dict子类化即可免费获得它们:

class AttrDict(dict):
    __getattr__ = dict.__getitem__
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

要获得默认为无的行为,只需将Python 2.5的collections.defaultdict类而不是dict子类化即可。

关于DictObj ,以下内容对您DictObj吗? 空白类将允许您随意添加或替换容器对象中的内容。

class Container(object):
    pass

>>> myContainer = Container()
>>> myContainer.spam = "in a can"
>>> myContainer.eggs = "in a shell"

如果您不希望在没有属性时不抛出AttributeError,那么您如何看待以下内容? 就个人而言,我更愿意使用dict来表示清楚,或使用try / except子句。

class QuietContainer(object):
    def __getattr__(self, attribute):
        try:
            return object.__getattr__(self,attribute)
        except AttributeError:
            return None

>>> cont = QuietContainer()
>>> print cont.me
None

对?

这是DictObj类的简单版本:

class DictObj(object):
    def __getattr__(self, attr):
        return self.__dict__.get(attr)

>>> d = DictObj()
>>> d.something = 'one'
>>> print d.something
one
>>> print d.somethingelse
None
>>> 

据我所知,Python类无论如何都使用字典来存储其属性(对程序员而言是隐藏的),因此在我看来,您在那里所做的工作实际上是在模仿Python类……使用python类。

这样做不是“错”的,如果您的字典在某个时候很有可能变成对象,那会更好,但是要当心要首先使用括号的原因:

  1. 点访问不能使用关键字作为键。
  2. 点访问必须在键中使用Python标识符有效的字符。
  3. 字典可以包含任何可哈希元素-不仅仅是字符串。

另外请记住,如果以后决定切换到对象,则始终可以像字典一样访问对象。

对于这种情况,我会默认使用“可读性计数”的口头禅:大概其他Python程序员将在阅读您的代码,并且他们可能不会期望到处都有字典/对象混合。 如果在特定情况下这是一个不错的设计决策,请使用它,但我不会在没有必要的情况下使用它。

和答案之间是对称的:

class dotdict(dict):
    __getattr__= dict.__getitem__
    __setattr__= dict.__setitem__
    __delattr__= dict.__delitem__

相同的接口,只是反过来实现了...

class container(object):
    __getitem__ = object.__getattribute__
    __setitem__ = object.__setattr__
    __delitem__ = object.__delattr__

使用类似DictObj之类的一个主要缺点是您要么必须限制允许的键,要么就不能在DictObj上使用诸如.keys() .values() .items()等方法。

不要忽视 。

它是Dictionary的子级,可以导入YAML或JSON,也可以将任何现有字典转换为Bunch,反之亦然。 一旦“打包”,字典将获得点符号,而不会丢失任何其他字典方法。

我个人喜欢点符号比字典字段好得多。 原因是它使自动完成工作更好。

如果达到您的目的还不错。 “实用胜过纯洁”。

我在其他地方(例如 )看到了这种方法,因此可以将其视为常见需求 (或期望)。

因为您要求不良的副作用:

缺点是,在类似eclipse + pyDev的可视编辑器中,您会在使用点表示法的行上看到许多未定义的变量错误。 Pydef将无法找到此类运行时“对象”定义。 而对于普通字典,它知道您只是在获取字典条目。

您将需要:1)忽略那些错误并使用红叉标记; 2)使用#@ UndefinedVariable逐行抑制这些警告,或3)完全禁用未定义??变量错误,导致您错过实际的未定义变量定义。

如果您正在寻找可处理嵌套字典的替代方法:

将字典递归地转换为所需类的实例

import json
from collections import namedtuple


class DictTransformer():
    @classmethod
    def constantize(self, d):
        return self.transform(d, klass=namedtuple, klassname='namedtuple')

    @classmethod
    def transform(self, d, klass, klassname):
        return self._from_json(self._to_json(d), klass=klass, klassname=klassname)

    @classmethod
    def _to_json(self, d, access_method='__dict__'):
        return json.dumps(d, default=lambda o: getattr(o, access_method, str(o)))

    @classmethod
    def _from_json(self, jsonstr, klass, klassname):
        return json.loads(jsonstr, object_hook=lambda d: klass(klassname, d.keys())(*d.values()))

例如:

constants = {
  'A': {
    'B': {
      'C': 'D'
    }
  }
}
CONSTANTS = DictTransformer.transform(d, klass=namedtuple, klassname='namedtuple')
CONSTANTS.A.B.C == 'D'

优点:

  • 处理嵌套的字典
  • 可能会产生其他类
  • namedtuple提供常量的不变性

缺点:

  • 如果您的klass中未提供.keys.values则它们可能不会响应。(尽管有时您可以模仿._fieldslist(ABC)

有什么想法吗?

h / t到@hlzr以获取原始的课堂想法

  相关解决方案