在 Bunch 类型对象中设置和获取属性
Set and Get attributes in Bunch type object
为简化 parse/create 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
并且在尝试设置属性时,
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)
似乎 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
嵌套的 EAFP 似乎有点难以维护,我的问题是:
- 有没有更简单的方法来处理 Bunch 数据对象的 get 和 set 函数?
- 是否有任何其他类似 Dict 的对象允许属性和键之间的可变性?
- Bunch 对象的
.update()
函数应该如何工作,浅拷贝还是深拷贝?或者只是让默认的 dict.update()
做它做的事? Understanding dict.copy() - shallow or deep?
幸运的是,所有对象都有一个类似 dict 的内部对象来管理对象的属性(这在 __dict__
属性中)。要执行您的要求,您只需让 class 将其自身用作 __dict__
对象:
class Bunch(dict):
def __init__(self, *args, **kwargs):
self.__dict__ = self
super().__init__(*args, **kwargs)
用法:
>>> b = Bunch()
>>> b.foo = 3
>>> b["foo"]
3
>>> b["foo"] = 5
>>> b.foo
5
>>> b["bar"] = 1
>>> b.bar
1
为简化 parse/create 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
并且在尝试设置属性时,
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)
似乎 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
嵌套的 EAFP 似乎有点难以维护,我的问题是:
- 有没有更简单的方法来处理 Bunch 数据对象的 get 和 set 函数?
- 是否有任何其他类似 Dict 的对象允许属性和键之间的可变性?
- Bunch 对象的
.update()
函数应该如何工作,浅拷贝还是深拷贝?或者只是让默认的dict.update()
做它做的事? Understanding dict.copy() - shallow or deep?
幸运的是,所有对象都有一个类似 dict 的内部对象来管理对象的属性(这在 __dict__
属性中)。要执行您的要求,您只需让 class 将其自身用作 __dict__
对象:
class Bunch(dict):
def __init__(self, *args, **kwargs):
self.__dict__ = self
super().__init__(*args, **kwargs)
用法:
>>> b = Bunch()
>>> b.foo = 3
>>> b["foo"]
3
>>> b["foo"] = 5
>>> b.foo
5
>>> b["bar"] = 1
>>> b.bar
1