python - 是否有等效于属性的部分方法?
问题描述
我有一个包含许多参数的类,这些参数存储在字典中,如下所示(实际上,它有点复杂,但这给出了一个好主意)。我可以使用以下方法“自动生成”获取和设置方法partialmethod
:
for a_name in ['x', 'y', 'z']:
locals()["get_" + a_name] = partialmethod(_get_arg,
arg_name=a_name)
locals()["set_" + a_name] = partialmethod(_set_arg,
arg_name=a_name)
理想情况下,我想使用@property
,但前提是我可以“自动生成@property
”@setter
和@deleter
. 这有没有可能?第二个片段显示了“手动”添加的属性;我正在研究使用等价物partialmethod
来避免重复和不可维护的代码。
class C:
def __init__(self):
self.kwargs = {'x' : 0, 'y' : 3, 'z' : True}
def __get_arg(self, arg_name):
assert arg_name in self.kwargs
return self.kwargs[arg_name]
def __set_arg(self, arg_name, value):
assert arg_name in self.kwargs
self.kwargs[arg_name] = value
def __del_arg(self, arg_name):
assert arg_name in self.kwargs
del self.kwargs[arg_name]
@property
def x(self):
return self.__get_arg('x')
@x.setter
def x(self, value):
self.__set_arg('x', value)
@x.deleter
def x(self):
self.__del_arg('x')
@property
def y(self):
return self.__get_arg('y')
@y.setter
def y(self, value):
self.__set_arg('y', value)
@y.deleter
def y(self):
self.__del_arg('y')
@property
def z(self):
return self.__get_arg('z')
@x.setter
def z(self, value):
self.__set_arg('z', value)
@x.deleter
def z(self):
self.__del_arg('z')
c = C()
c.x = 'foo' # setter called
foo = c.x # getter called
del c.x # deleter called
解决方案
对于您的特定示例,执行此操作的更简单方法可能是子类
dict
化然后定义魔术方法__getattr__
, __setattr__
,并且
__delattr__
在属性不存在时分别调用这些方法。然后你可以调用super()
从dict
类继承行为。
class AttrDict(dict):
attrs = ("x", "y", "z")
def __getattr__(self, name):
if not name in self.attrs:
raise AttributeError(name)
try:
return super().__getitem__(name)
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
if not name in self.attrs:
raise AttributeError(name)
try:
return super().__setitem__(name, value)
except KeyError:
raise AttributeError(name)
def __delattr__(self, name):
if not name in self.attrs:
raise AttributeError(name)
try:
return super().__delitem__(name)
except KeyError:
raise AttributeError(name)
>>> obj = AttrDict(x=24)
>>> obj.x
24
>>> obj.a = 1
AttributeError: a
>>> obj.y = 25
>>> obj.y
25
>>> del obj.y
>>> obj.y
AttributeError: y
>>> obj.kwargs["z"] = 26
>>> obj.z
26
如果您不关心限制特定属性,那就更容易了。您可以简单地将每个__*attr__
方法分配给其对应的
dict.__*item__
方法,这就是订阅操作所调用的方法。(即obj[key]
)
class AttrDict(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
>>> obj = AttrDict({"a": 1})
>>> obj.a
1
>>> obj["b"] = 2
>>> obj.b
2
>>> del obj.b
>>> obj.b
KeyError
推荐阅读
- react-native - NPM 安装在 React Native 中导致大量错误
- c - 如何在 C 中使用 write() 函数编写整数?
- javascript - 使用带有 HTTPS Post 请求的 create 方法时出错 [ReactJs]
- php - 如何在 Laravel 6 刀片视图中的请求中获取值是否在数组内部?
- css - 使用 Rails 字符串插值在 HTML 中添加多个条件 CSS 类
- angular-material - 角度材料在表中组合相同的列值,并仅显示多行的单个值
- firebase - Flutter + firestore:过滤器列表
- html - VBA中的getattribute无法比较记录集中的值
- function - PostgreSQL 函数返回类型记录显示错误
- c++ - 如何修复这个*尝试*将美元转换为人民币和韩元的 C++ 程序?