检查属性是否可设置/删除
我该如何检查一个属性在Python中是否可以设置或删除呢?
到目前为止,我找到的最好方法是
type(obj).__dict__["prop_name"].fset is not None
3 个回答
1
下面这个程序测试了三个函数,这些函数的目的是检查一个类或者实例的属性是否支持CRUD操作。这里的类或实例是传给can_*
函数的第一个参数,而第二个参数是需要检查的属性名称。程序会自动进行类型检查,以确保这些函数的使用是符合预期的。请注意,这些函数只适用于使用builtins
模块中的property
类创建的属性。
#! /usr/bin/env python3
def main():
for kind in Test, TestG, TestS, TestGS, TestD, TestGD, TestSD, TestGSD:
print(kind.__name__, 'Class')
print(' can_get:', can_get(kind, 'data'))
print(' can_set:', can_set(kind, 'data'))
print(' can_del:', can_del(kind, 'data'))
print()
instance = kind('Hello, world!')
print(kind.__name__, 'Instance')
print(' can_get:', can_get(instance, 'data'))
print(' can_set:', can_set(instance, 'data'))
print(' can_del:', can_del(instance, 'data'))
print()
def can_get(obj, key):
return _get_property(obj, key).fget is not None
def can_set(obj, key):
return _get_property(obj, key).fset is not None
def can_del(obj, key):
return _get_property(obj, key).fdel is not None
def _get_property(obj, key):
if not isinstance(obj, type):
obj = type(obj)
pro = vars(obj).get(key)
if not isinstance(pro, property):
raise TypeError('{.__name__}.{} is not a property'.format(obj, key))
return pro
class Test:
def __init__(self, value):
self.__data = value
def get_data(self):
return self.__data
def set_data(self, value):
self.__data = value
def del_data(self):
del self.__data
data = property()
class TestG(Test):
data = property(fget=Test.get_data)
class TestS(Test):
data = property(fset=Test.set_data)
class TestGS(Test):
data = property(fget=Test.get_data, fset=Test.set_data)
class TestD(Test):
data = property(fdel=Test.del_data)
class TestGD(Test):
data = property(fget=Test.get_data, fdel=Test.del_data)
class TestSD(Test):
data = property(fset=Test.set_data, fdel=Test.del_data)
class TestGSD(Test):
data = property(fget=Test.get_data, fset=Test.set_data, fdel=Test.del_data)
if __name__ == '__main__':
main()
1
我觉得在尝试之前是没办法提前知道的。你不能确定一个对象是否有奇怪的 __setattr__
或者类似的东西,这可能会破坏你想要使用的抽象概念。
8
这是一个很好的例子,说明你应该遵循“请求原谅比请求许可更容易”的原则,也就是说,遇到问题时直接处理错误就行,特别是当某个属性不能被设置或删除时。
try:
x.prop = 42
except AttributeError:
pass