Python标准库中类似JavaScript的对象?

时间:2010-04-14 20:29:35

标签: python

很多时候,我发现自己想在Python中使用一个简单的“转储”对象,其行为类似于JavaScript对象(即,可以使用.member['member']访问其成员。)< / p>

通常我会把它放在.py

的顶部
class DumbObject(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __stattr__(self, attr, value):
        self[attr] = value

但是这有点蹩脚,而且实现中至少有一个错误(虽然我不记得它是什么)。

那么,标准库中是否有类似内容?

而且,为了记录,只是实例化object不起作用:

>>> obj = object()
>>> obj.airspeed = 42
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'object' object has no attribute 'airspeed'

编辑 :(当然,应该看到这一个来了)......别担心!我不是想用Python编写JavaScript。我经常发现我想要的地方就是在我还在试验的时候:我有一些“东西”的集合,这些东西不太适合放入字典,但也不适合拥有自己的课程

10 个答案:

答案 0 :(得分:12)

您可以尝试使用attrdict

class attrdict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.__dict__ = self

a = attrdict(x=1, y=2)
print a.x, a.y
print a['x'], a['y']

b = attrdict()
b.x, b.y  = 1, 2
print b.x, b.y
print b['x'], b['y']

答案 1 :(得分:7)

这种物体没有“标准库”,但在ActiveState上有一个来自Alex Martelli的着名食谱,名为"bunch"

注意:在pypi上还有一个名为bunch的软件包,应该做同样的事情,但我对它的实现和质量一无所知。

答案 2 :(得分:7)

您可能对collections.namedtuple

感兴趣

答案 3 :(得分:6)

如果我理解正确,您需要一个可以转储属性的对象。如果我是对的,你所要做的就是创建一个空类。例如:

>>> class DumpObject: pass
... 
>>>#example of usage:
...
>>> a = DumpObject()
>>> a.airspeed = 420
>>> print a.airspeed
420

就是这样

答案 4 :(得分:3)

在Python 3.3及更高版本中,您可以使用SimpleNamespace,它完全可以满足您的需求:

from types import SimpleNamespace
obj = SimpleNamespace()
obj.airspeed = 42

https://docs.python.org/3.4/library/types.html#types.SimpleNamespace

答案 5 :(得分:1)

我不是那个人的忠实粉丝,因为你进入了“如果你定义'键'会怎么样'”:

foo = DumbObject()
foo.moshe = 'here'
foo.keys # --> gives a callable, if you'll call it you'll get ['moshe']
foo.keys = 'front-door'
foo.keys # --> oh look, now it's a string 'front-door'

“钥匙”应该是您对象的已定义方法,还是仅仅是偶然的?如果是,则最好将DumbObject定义为

class DumbObject(object):
    def __init__(self):
        self._dict = {}
    def __getitem__(self, key):
        return self._dict[key]
    __getattr__ = __getitem__
    # Ditto for set
def asDictionary(do):
    return do._dict

但你为什么要这样做?你确定这是正确的答案吗?也许你应该使用正确类型的对象?

答案 6 :(得分:1)

好吧,据我所知(如果我错了,请纠正我)这里的每个例子都没有将嵌套字典转换为新类型。所以我做了这个例子:

class DotDictionary(dict):

def __init__(self, init_value):
    if not isinstance(init_value, dict):
        raise TypeError('Expected dict, got {}'.format(type(init_value)))

    self._dict_to_self(init_value)

def __getattr__(self, name):
    return self[name]

def __setattr__(self, name, val):
    self[name] = val

def __delattr__(self, name):
    del self[name]

def _dict_to_self(self, dct):
    for key, value in dct.items():
        if isinstance(value, dict):
            value = DotDictionary(value)
        if isinstance(value, (tuple, list)):
            for i, _ in enumerate(value):
                if isinstance(value[i], dict):
                    value[i] = DotDictionary(value[i])

        self[key] = value

ideone

我并非100%确定它的工作原理绝对正确,因此不在此保修。

也许它不是pythonic-way所以我准备好接受建议。

答案 7 :(得分:0)

此方法适用于嵌套字典,并且非常简洁。

首先,定义一个空类。此类的实例可以设置任何属性。

class holder:
    pass

接下来,只需使用此功能即可。

def dotted(object):

    if isinstance(object, dict):
        parent = holder()

        for key in object:

            child = object.get(key)
            setattr(parent, key, dotted(child))

        return parent

    return object

示例用法。

users = dotted(
{
    'john': {
        'fullname': 'John Doe'
        'age': 24,
        'hobbies': [
            'programming',
            'jogging'
        ]
    }
}

users.john.fullname # 'John Doe'
users.john.age      # 24
users.john.hobbies  # ['programming', 'jogging']

users.john.age = 25
users.john.age      # 25

答案 8 :(得分:0)

DumbObject = lambda: "function is a first-class object And this sentence isn't necessary :), you could simply put None or Pass"

DumbObject.name = "Dumb"
DumbObject.speak = lambda word: print(word)
DumbObject.tell_name =  lambda : print(f"I am {DumbObject.name} and have no self")

DumbObject.speak("I speak not")
DumbObject.tell_name()

答案 9 :(得分:0)

此实现允许您任意嵌套 dictSimpleNamespace,并且与 json.dumps 兼容,因为它继承自 dict

from types import SimpleNamespace
import json


class DictNamespace(dict):

    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = self.construct_namespace(value)

    def __delattr__(self, key):
        del self[key]

    @staticmethod
    def construct_namespace(maybe_dict):
        if isinstance(maybe_dict, dict):
            for key, value in maybe_dict.items():
                if isinstance(value, dict):
                    maybe_dict[key] = DictNamespace(**value)
                elif isinstance(value, SimpleNamespace):
                    maybe_dict[key] = DictNamespace(**value.__dict__)
                else:
                    maybe_dict[key] = value
        return maybe_dict

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        DictNamespace.construct_namespace(self)


thing = DictNamespace(
    one=1, 
    two=dict(three=3), 
    five=DictNamespace(six=6), 
    eight=SimpleNamespace(nine=9)
)

thing.eleven = 11
print(thing.one)
print(thing.two)
print(thing.two.three)
print(thing.five)
print(thing.five.six)
print(thing.eight)
print(thing.eight.nine)
print(thing["eight"]["nine"])
print(thing["eight"].nine)
print(thing.eleven)
del thing.eleven
assert thing.get("eleven", None) is None
print(json.dumps(thing))