简体   繁体   中英

python assign build-in property function to list element

I don't understand why the following code gives two different outputs

class foo(object):

       def myget(self):
          return 3

       goo=property(myget)

       hh1=[1,2,3]
       hh1[0]=property(myget)

       def hh(self):
         print self.goo
         print self.hh1[0]
ff=foo()
ff.hh()       

output:

 3
 <property object at 0x292a998>

Thanks

property objects are descriptors . Descriptors only have special powers when bound to a class. Otherwise, they behave exactly like any other class. When you put the property in a list, it is not bound to the class, so it loses it's special properties.


For an example, let's look at an implementation of property written in pure python as descriptors:

class Property(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"

    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        self.__doc__ = doc

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError, "unreadable attribute"
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError, "can't set attribute"
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError, "can't delete attribute"
        self.fdel(obj)

Notice how the second argument to __get__ , __set__ and __delete__ are obj? obj is the instance of the class that the descriptor is bound to (it gets passed to the method as self if that help clarify things). In order for the whole shebang to work, the descriptor must be bound to a class so that __get__ can be called and obj can be passed to it. If the descriptor isn't bound to a class, then __get__ doesn't get called and your descriptor class becomes just another class with a couple of magic methods that never get called (unless you call them explicitly).

Maybe slightly more concretely, when you do:

a = instance.my_descriptor

this calls my_descriptor.__get__(instance) and correspondingly:

instance.my_descriptor = a

calls my_descriptor.__set__(instance,a)

However, if my_descriptor isn't bound to a class, then it behaves just like any other class (object) which explains what you're seeing.

i think it may be related to dict . descriptor (property) only respond to attributes inside object or class dict . Both hh1[] and goo are in foo. dict . but hh1[0] is not, therefore, descriptor doesnt work in hh1[0].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM