很多时候,我发现自己想在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。我经常发现我想要的地方就是在我还在试验的时候:我有一些“东西”的集合,这些东西不太适合放入字典,但也不适合拥有自己的课程
答案 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)
答案 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
我并非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)
此实现允许您任意嵌套 dict
和 SimpleNamespace
,并且与 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))