質問

Imagine I've got this Python descriptor:

class MyDesc(object):
    def __get__(self, instance, instance_type=None):
        return 'Blue berries'
    def __set__(self, instance, value):
        print 'called with', instance, value

class MyClass(object):
    desc = MyDesc()

Is there a way in the normal run of things thar __set__ would get called with None for an instance argument? I mean without doing something like

MyClass.__dict__['desc'].__set__(None, 'ants bees cats')

These don't seem to do it:

MyClass.desc = 'blah'
setattr(MyClass, 'desc', 'blah')

The reason I ask is I see some defensive coding in Django to avoid this scenario, and I'm questioning whether it's necessary.

役に立ちましたか?

解決

I think you are right to question this test, and I can't find a way for instance to be None in this code either. The documentation also seems to make it clear that instance can never be None:

object.__set__(self, instance, value)

Called to set the attribute on an instance instance of the owner class to a new value, value.

My guess is that instance was checked for None in __get__ for a good reason, and that the same test ended up in __set__ by sheer mimetism.

他のヒント

As for the defensive coding, I see some code checking that there's an instance on __get__ (which gets called for MyClass.desc) but not on __set__. The reason it doesn't happen with __set__ is that setting the reference in the class replaces the whole descriptor reference.

I'd advise against excessively defensive programming, simply because the other code can find any way to go wrong with or without your assistance. It's enough to prevent surprising results rather than guard against active abuse.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top