简体   繁体   中英

Python 'Property' behave strangely

Look at the code below.

class CCC:
    @property
    def n(self):
        print('getter called')
        return self.__dict__['n']

    @n.setter
    def n(self, value):
        print('setter called')
        self.__dict__['n'] = value


c = CCC()
c.n = 5
print(CCC.__dict__)
print(c.__dict__)
print(c.n)

It is the result of execution

setter called
{'__module__': '__main__', 'n': <property object at 0x000000000289CC28>, '__dict__': <attribute '__dict__' of 'CCC' objects>, '__weakref__': <attribute '__weakref__' of 'CCC' objects>, '__doc__': None}
{'n': 5}
getter called # I do not understand why this sentence is printed. 
5

I do not understand why 'getter' was printed. CCC has an n property object. c has an n as integer. when I print cn , must print just c.\\__dict__['n'] . Instead, 'getter called' was printed. What am I misunderstanding?

First, you shouldn't be messing with stuff like __dict__ (or anything with a surrounded by __ ) unless you really know what you're doing and really need it.

That said, you create a property with a getter (implicit) and a setter (explicit). The getter returns the value self.__dict__['n'] while the setter assigns a value there.

Later on, you create an instance of CCC and use the setter in cn = 5 . Then you're printing the __dict__ of the CCC class which is telling you there is a property called n . Afterwards, you see the __dict__ of your instance c which due to the setting holds the value 5 .

So, since you're accessing the n property when doing cn . When you're doing self.__dict__['n'] you're also getting the value stored there, which you did define, via the setter, as 5 .

And since you wrote a print function in your getter, then that's what you get printed.

Perhaps doing by calling the key in the __dict__ in the setter/getter would help you declutter your thought

class CCC:
    @property
    def n(self):
        print('getter called')
        return self.__dict__['nval']

    @n.setter
    def n(self, value):
        print('setter called')
        self.__dict__['nval'] = value


c = CCC()
c.n = 5
print(CCC.__dict__)
print(c.__dict__)
print(c.n)

Now we don't have a mental name collision between the property n and the key in __dict__ .

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