我可以在Python中创建类似JavaScript的对象吗?
我可以在Python中创建类似JavaScript的对象吗?
我对Python非常陌生,希望能够使用.
来访问dict
的值。\n假设我有如下的test
:\n
>>> test = dict() >>> test['name'] = 'value' >>> print(test['name']) value
\n但我希望能够通过test.name
来获取value
。事实上,通过在我的类中重写__getattr__
方法,我已经实现了这一点,代码如下:\n
class JuspayObject: def __init__(self,response): self.__dict__['_response'] = response def __getattr__(self,key): try: return self._response[key] except KeyError,err: sys.stderr.write('Sorry no key matches')
\n这样做是有效的!当我执行以下代码时:\n
test.name // 我得到了value。
\n但是问题是,当我只打印test
本身时,会出现错误:\n
'Sorry no key matches'
\n为什么会发生这种情况?
在上述答案的基础上,我们可以添加对嵌套字典的支持:
from types import SimpleNamespace class NestedNamespace(SimpleNamespace): def __init__(self, dictionary, **kwargs): super().__init__(**kwargs) for key, value in dictionary.items(): if isinstance(value, dict): self.__setattr__(key, NestedNamespace(value)) else: self.__setattr__(key, value) nested_namespace = NestedNamespace({ 'parent': { 'child': { 'grandchild': 'value' } }, 'normal_key': 'normal value', }) print(nested_namespace.parent.child.grandchild) # value print(nested_namespace.normal_key) # normal value
请注意,这不支持对位于列表中的字典的点表示法。
在Python中是否可以创建类似JavaScript对象的问题,其出现的原因是因为提问者想要借用JavaScript的语法。然而,通过个人经验可以得知,这并不是一个好主意。尽管它看起来更简洁,但从长远来看,它只会变得晦涩难懂。字典就是字典,试图让它们像带有属性的对象一样行为可能会导致(不好的)意外。如果你需要像操作字典一样操作对象的字段,可以在需要时使用内部__dict__
属性,这样可以明确地知道你在做什么。或者使用getattr(obj, 'key')
来考虑继承结构和类属性。但根据你的示例,似乎你正在尝试做一些不同的事情...因为点运算符已经会自动查找__dict__
属性,无需额外的代码。一个糟糕的意外示例是:如果字典中的键恰好是Python的关键字,例如字符串'for'
,那么属性访问将失败,而且没有优雅的方式来处理这种情况。这个整体思路从一开始就是错误的。另一方面,自动补全可以实现更高效、更少出错的代码。如果字典结构可以预定义的话,这将完美地工作。JavaScript是优雅的。JavaScript可以是优雅的,也可以是一团糟(像大多数语言一样)。但保证是一团糟的是试图将Python用作JavaScript(或任何其他两种语言)的做法。如果在给定的语言中有一种预期的方法来做某事,偏离这种方法只会带来痛苦。
在Python中,我们可以使用types模块中的SimpleNamespace类来创建类似于JavaScript的对象。通过使用SimpleNamespace类,我们可以轻松地添加、修改和删除值,只需使用常规的属性访问即可。
以下是使用SimpleNamespace类创建JavaScript-like对象的示例代码:
from types import SimpleNamespace d = {'key1': 'value1', 'key2': 'value2'} n = SimpleNamespace(**d) print(n) # 输出:namespace(key1='value1', key2='value2') print(n.key2) # 输出:'value2' # 修改属性值 n.key2 = 'new value' print(n.key2) # 输出:'new value' # 删除属性 del n.key1 print(n) # 输出:namespace(key2='new value') # 转换回字典 print(vars(n)) # 输出:{'key2': 'new value'}
需要注意的是,字典中的键必须是字符串标识符,以便正确访问属性。SimpleNamespace类是在Python 3.3中添加的,对于旧版本的Python,可以使用argparse模块中的Namespace类来实现类似的功能。
此外,第三方库python-box也提供了类似的功能,可以递归访问对象的属性。可以通过在命令行中运行`pip install python-box`来安装该库。
需要注意的是,当使用SimpleNamespace类时,`'key' in d`这样的判断语句将不起作用,因为SimpleNamespace对象不支持in运算符。