滥用'属性'保留字

时间:2016-05-19 05:18:16

标签: python python-2.7 properties decorator

所以我有一些使用保留字property的上帝遗弃的遗留代码,这是错误的。在继承的基类中,它们已基本实现。

class TestClass(object):

    def __init__(self, property):
        self._property = property

    @property
    def property(self):
        return self._property


test = TestClass('test property')
print(test.property)

哪个运行没有错误。如果您在下面添加另一种方法,

class TestClass2(object):

    def __init__(self, property):
        self._property = property

    @property
    def property(self):
        return self._property

    @property
    def other_property(self):
        return 'test other property'


test = TestClass2('test property')
print(test.property)
print(test.other_property)

引发:

---> 10     @property
     11     def other_property(self):
     12         print('test other property')

TypeError: 'property' object is not callable

因为您知道在本地命名空间中覆盖了property

class TestClass3(object):

    def __init__(self, property):
        self._property = property

    @property
    def other_property(self):
        return 'test other property'

    @property
    def property(self):
        return self._property


test = TestClass3('test property')
print(test.property)
print(test.other_property)

如果您始终在课程底部定义property覆盖,则可以解决此问题。如果仅在基类上定义property方法,那么从事物中继承的方法也可以解决,因为名称空间。

class TestClass4(TestClass):

    def __init__(self, property):
        super(TestClass4, self).__init__(property)

    @property
    def other_property(self):
        return 'test other property'


test = TestClass4('test property')
print(test.property)
print(test.other_property)

我的正义愤慨说我们必须在大量的遗留代码中更新这个变量名,因为GAAAAH,但除了必须记住在很少修改的基础上添加property定义的定义之上的新方法上课,这实际上没有什么可以解决的吗?

3 个答案:

答案 0 :(得分:4)

不要影子内置...... 几乎没有任何重构你可以避免完全遮蔽内置

使用__getattr__代替@property返回您的_property会员...

class TestClass(object):
    def __init__(self):
        self._property = 12

    def __getattr__(self,item):
        if item == "property": 
           #do your original getter code for `property` here ... 
           # now you have not overwritten the property keyword at all
           return getattr(self,"_property") # just return the variable
class TestClass2(TestClass):
    def __init__(self):
        self._property = 67

print TestClass2().property

class MySubClass(TestClass):
    @property
    def a_property(self):
        return 5

print MySubClass().property
print MySubClass().a_property

真的,顺便说一下,在python中使用@property并不是什么好理由。它所做的一切最终会让其他程序员感到困惑,并且模糊了你实际调用函数的事实。我曾经经常这样做...我现在避免它,除非我有一个非常令人信服的理由不

答案 1 :(得分:3)

是的,如果你总是property方法的定义之上添加新方法,那么什么都不会破坏。因此,在代码中对该效果进行了很好的评论。希望任何想要在派生类中覆盖property的人都会首先查看基类并看到你的评论......

顺便说一下,property方法的__init__ arg也会影响property,但我想这不是问题。

理想情况下,有人应该清理这个混乱,但我知道这样做可能不符合成本效益。

另外,我有些困惑为什么原来的编码器首先让property成为@property。仅当必须动态计算属性的值时才应使用该构造,而不是仅仅返回静态属性。也许他们是Python的新手,他们被告知这是用Python做getter的方法......

答案 2 :(得分:0)

您可以随时将property重新映射到其他名称。只要您选择一个与您的其他类属性不匹配的名称,并且它不会在该类的外部接口中公开,那么您命名它的名称并不重要。

tproperty = property

class Test(...)

    @tproperty
    def property(self):
        ....