alv*_*vas 5 python dictionary data-structures bunch
为了简单解析/创建 JSON,机器学习应用程序通常使用Bunch对象,例如https://github.com/dsc/bunch/blob/master/bunch/__init__.py
获取时,有一个嵌套的 EAFP 习语,它检查dict.get()函数,然后尝试使用字典方括号语法访问它,即
class Bunch(dict):
def __getattr___(self, k):
try:
return object.__getattribute__(self, k)
except AttributeError:
try:
return self[k]
except KeyError:
raise AttributeError
Run Code Online (Sandbox Code Playgroud)
当试图设置一个属性时,
def __setattr__(self, k, v):
try:
# Throws exception if not in prototype chain
object.__getattribute__(self, k)
except AttributeError:
try:
self[k] = v
except:
raise AttributeError(k)
else:
object.__setattr__(self, k, v)
Run Code Online (Sandbox Code Playgroud)
似乎sklearn实现遵循相同的思路,但检查较少https://github.com/scikit-learn/scikit-learn/blob/2beed5584/sklearn/utils/__init__.py#L61
class Bunch(dict):
def __init__(self, **kwargs):
super().__init__(kwargs)
def __setattr__(self, key, value):
self[key] = value
def __dir__(self):
return self.keys()
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(key)
def __setstate__(self, state):
# Bunch pickles generated with scikit-learn 0.16.* have an non
# empty __dict__. This causes a surprising behaviour when
# loading these pickles scikit-learn 0.17: reading bunch.key
# uses __dict__ but assigning to bunch.key use __setattr__ and
# only changes bunch['key']. More details can be found at:
# https://github.com/scikit-learn/scikit-learn/issues/6196.
# Overriding __setstate__ to be a noop has the effect of
# ignoring the pickled __dict__
pass
Run Code Online (Sandbox Code Playgroud)
嵌套的 EAFP 似乎有点难以维护,我的问题是:
.update()函数应该如何工作,浅拷贝还是深拷贝?或者只是让默认dict.update()做它所做的? 理解 dict.copy() - 浅还是深?幸运的是,所有对象都有一个内部类似字典的对象,用于管理对象的属性(这是在属性中__dict__)。要执行您所要求的操作,您只需使该类使用自身作为对象即可__dict__:
class Bunch(dict):
def __init__(self, *args, **kwargs):
self.__dict__ = self
super().__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
用法:
>>> b = Bunch()
>>> b.foo = 3
>>> b["foo"]
3
>>> b["foo"] = 5
>>> b.foo
5
>>> b["bar"] = 1
>>> b.bar
1
Run Code Online (Sandbox Code Playgroud)