Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
737 views
in Technique[技术] by (71.8m points)

oop - Python overriding getter without setter

class human(object):
    def __init__(self, name=''):
        self.name = name

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

class superhuman(human):
    @property
    def name(self):
        return 'super ' + name

s = superhuman('john')
print s.name

# Doesn't work :( "AttributeError: can't set attribute"
s.name = 'jack'
print s.name

I want to be able to override the property but be able to use the super parent's setter without having to override the setter in the child class.

Is that pythonicaly possible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use just the .getter decorator of the original property:

class superhuman(human):
    @human.name.getter
    def name(self):
        return 'super ' + self._name

Note that you have to use the full name to reach the original property descriptor on the parent class.

Demonstration:

>>> class superhuman(human):
...     @human.name.getter
...     def name(self):
...         return 'super ' + self._name
... 
>>> s = superhuman('john')
>>> print s.name
super john
>>> s.name = 'jack'
>>> print s.name
super jack

The property descriptor object is just one object, even though it can have multiple methods associated with it (the getter, setter and deleter). The .getter, .setter and .deleter decorator functions provided by an existing property descriptor return a copy of the descriptor itself, with that one specific method replaced.

So in your human base class what happens is that you first create the descriptor with the @property decorator, then replace that descriptor with one that has both a getter and a setter with the @name.setter syntax. That works because python decorators replace the original decorated function with the same name, it basically executes name = name.setter(name). See How does the @property decorator work? for the details on how that all works.

In your subclass you simply use that trick to create a new copy of the descriptor with just the getter replaced.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...