Проверка, может ли свойство настраиваться/удаляться
Как проверить, является ли свойство настраиваемым или удаляемым в Python?
Лучшее, что я нашел до сих пор,
type(obj).__dict__["prop_name"].fset is not None
Ответы
Ответ 1
Это хороший случай, когда вы должны подписаться на философию "Это проще просить прощения, чем разрешение", и просто обрабатывать исключение, если свойство не может быть установлено/удалено.
try:
x.prop = 42
except AttributeError:
pass
Ответ 2
Я не думаю, что есть какой-то способ узнать себя, не пытаясь. Вы не можете точно знать, есть ли у объекта странный __setattr__
или похожий, который разрушит абстракцию, которую вы пытаетесь использовать.
Ответ 3
Следующая программа проверяет три функции, предназначенные для выяснения того, поддерживает ли свойство класса или экземпляра операции CRUD. Класс или экземпляр является первым аргументом функций can_*
, а вторым аргументом является имя свойства, которое должно быть проверено. Проверка типов выполняется автоматически, чтобы гарантировать, что функции используются, как ожидалось. Обратите внимание, что это предназначено только для работы со свойствами, созданными с помощью класса property
из модуля builtins
.
#! /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()