简体   繁体   English

python class:为什么在尝试使用 @property 装饰器设置属性时获得最大递归?

[英]python class: why do I get maximum recursion when trying to set an attribue with @property decorator?

I am learning how to create classes in python where when modifying attribute 1 will change attribute 2. For instance a circle with an attribue radius.我正在学习如何在 python 中创建类,其中在修改属性 1 时将更改属性 2。例如具有属性半径的圆。

class Circle():
    def __init__(self,radius):
        self._radius = radius
        
    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self.radius = value
    
    @property
    def area(self):
        return 3.14*self.radius*self.radius
    

And this happens:这会发生:

c = Circle(3)
c.area

All fine.一切都好。 but now:但现在:

c.radius = 56
print(c.area)

gives:给出:

RecursionError: maximum recursion depth exceeded

The question is why?问题是为什么? What is the way to force recalculation of other attributes when one is changed?当一个属性被改变时,强制重新计算其他属性的方法是什么?

I have consulted several answers: Python: modifying property value How do you change the value of one attribute by changing the value of another?我查阅了几个答案: Python:修改属性值如何通过更改另一个属性的值来更改一个属性的值? (dependent attributes) (依赖属性)

EDIT: According to some answers (see bellow) I am in an infinite loop.编辑:根据一些答案(见下文)我处于无限循环中。 So I delete the part of the setter.所以我删除了setter的部分。 I remain with:我留在:

class Circle():
    def __init__(self,radius):
        self._radius = radius
        
    @property
    def radius(self):
        return self._radius
    
    @property
    def area(self):
        return 3.14*self.radius*self.radius
    

What happens then is:然后发生的是:

c = Circle(3)
c.radius = 30

error: AttributeError: can't set attribute错误:AttributeError:无法设置属性

After the comments posted here this is the answer with exploratory explanation:在此处发布评论之后,这是带有探索性解释的答案:

class Circle():
    def __init__(self, _radius, color):
        print('init run')
        self._radius = _radius
        self.color = color
        
    @property
    def radius(self):
        print('property radius run')
        return self._radius
    
    @radius.setter
    def radius(self, value):
        print('setter radius run')
        self._radius = value
    
    @property
    def area(self):
        print('property AREA run')
        return 3.14*self.radius*self.radius
    

I added print statements because if you want to find out what really happens I recommend you to run this code in separate cells in a notebook:我添加了打印语句,因为如果您想了解实际发生了什么,我建议您在笔记本的单独单元格中运行此代码:

c= Circle(3,'azul') # here only __init__ runs
print(c.radius) # here property radius run

print(c.area) 

This is the interesting part.这是有趣的部分。 When printing c.area things happen.打印 c.area 时发生了事情。 Before running the code think about what do you think it would happenI was surprised but relieved because I understood now the functioning.在运行代码之前想想你认为它会发生什么我很惊讶但又松了一口气,因为我现在理解了它的功能。 This is what happens: property AREA run, property radius run, property radius run.这就是发生的情况:属性区域运行,属性半径运行,属性半径运行。 My lessons learnt: Accessing the radius property is done via the method.我的经验教训:访问半径属性是通过方法完成的。 This WAS NOT AT ALL OBVIOUS FOR ME.这对我来说一点也不明显。

Now try to change the radius现在尝试改变半径

c.radius = 56 # setter method runs

print(c.area)   # the same ass before. 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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