检查属性是否可设置/可删除

时间:2011-05-23 20:37:30

标签: python properties

如何在Python中检查属性是否可设置或可删除?

到目前为止我发现的最好的是

type(obj).__dict__["prop_name"].fset is not None

3 个答案:

答案 0 :(得分:8)

这是一个很好的情况,当你应该订阅“请求宽恕而不是权限”的理念时,如果属性可设置/可删除,只需处理异常。

try:
    x.prop = 42
except AttributeError:
    pass

答案 1 :(得分:1)

我认为没有任何方法可以在不尝试的情况下预先知道。您无法确定某个对象是否有一个奇怪的__setattr__或类似的东西会破坏您尝试使用的抽象。

答案 2 :(得分:1)

以下程序测试三个函数,用于确定类或实例属性是否支持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()