質問

class Silly:
    @property
    def silly(self):
        "This is a silly property"
        print("You are getting silly")
        return self._silly

    @silly.setter
    def silly(self, value):
        print("You are making silly {}".format(value))
        self._silly = value

    @silly.deleter
    def silly(self):
        print("Whoah, you killed silly!")
        del self._silly

s = Silly()
s.silly = "funny"
value = s.silly
del s.silly

But it does not print "You are getting silly", "You are making silly funny",... as expected. Don't know why. Can you have me figure out, folks?

Thanks in advance!

役に立ちましたか?

解決

The property decorator only works with new-style classes (see also). Make Silly extend from object explicitly to make it a new-style class. (In Python 3, all classes are new-style classes)

class Silly(object):
    @property
    def silly(self):
        # ...
    # ...

他のヒント

As you most likely are aware of the correct method to add properties would be to use:

@property
def silly(self):
    return self._silly


@silly.setter:
def silly(self, value):
    self._silly = value

But this requires new style classes, that is that somewhere in the chain there is supposed to be a class ParentClass(object):. The similar option of using silly = property(get_silly, set_silly) has the same requirement.

However, there is another option, and that is to use a corresponding private variable, like self._silly, and override the __getattr__ and __setattr__ methods:

def __getattr__(self, name): 
    """Called _after_ looking in the normal places for name."""  

    if name == 'silly':
        self._silly
    else:
        raise AttributeError(name)


def __setattr__(self, name, value):
    """Called _before_ looking in the normal places for name."""
    if name == 'silly':
        self.__dict__['_silly'] = value
    else:
        self.__dict__[name] = value

Notice how __getattr__ will be called after checking for other attributes, but that __setattr__ is called before checking for other attributes. Therefore the former can and should raise an error if not an accepted attribute, and the latter should set the attribute. Do not use self._silly = value within __setattr__ as that would cause infinite recursion.

Also note that since we're dealing with old style classes here, you should actually use the dict method, and not the newer baseclass.__setattr__(self, attr, value), see docs. A similar __delattr__() does also exist, if you want it.

Using this code, you can now do stuff like:

i_am = Silly()
i_am.silly = 'No, I'm clever'
print i_am.silly
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top