2013-10-24 21 views
2

很多时候我的类有几个属性,而其他对象的属性依赖于这些属性。什么是定义和访问这些的最佳方式? 一个简单的例子应该解释我在问什么。链接到他人的对象属性:如何保持一致性?

说我有一个类,定义了一个圈:

class Circle: 
    def __init__(self, r): 
     self.r = r 

现在这个圈子里被实例化正是基于半径,但我可能希望能够访问它的直径,这些都是可能性我见:

A)创建一个新的属性实例

class Circle: 
    def __init__(self, r): 
     self.r = r 
     self.d = 2*r 

B时的)定义返回的直径的函数

class Circle: 
    def __init__(self, r): 
     self.r = r 
    def d(self): 
     d = 2*r 
     return d 

解决方案A不保证一致性,如果用户更改r,d不会自动更新,并且可能很难追踪到该错误。解决方案B要求用户调用函数而不是访问属性。每次必须访问属性d时,都必须重新计算属性d,并且通常可能会耗费大量时间。

是否有解决方案C确保一致性,并且不需要类用户在每次访问时重新计算属性?

+0

我在问自己同样的问题,但我对所给的回应并不满意。我认为必须有一个更加优雅的方法来解决这个问题...... – MonkeyButter

回答

1

你可以在这里使用Python属性。

下面是内置的属性函数在文档中进行讨论:

http://docs.python.org/2/library/functions.html#property

在你的情况,你可以按如下方式使用它:

def getdiameter(self): 
    return self.r * 2 

def setdiameter(self, d): 
    self.r = d/2 

d = property(getdiameter, setdiameter) 

您可能希望d是只读(这纯粹是一个半径的函数)。在这种情况下,您可以从属性中省略setdiameter函数。

更新 如果d是非常昂贵的计算,那么我会计算d时,它是第一次读取和无效d时计算r。

def setr(self, r): 
    self.r = r 
    self.d = None 

def getd(self): 
    if not self.d is None: 
     return self.d 
    self.d = self.r * 2 # Our expensive calculation 
    return self.d 
+2

你应该使用'@ property'装饰器。它提高了可读性。 – ninMonkey

+0

这是我会这样做的方式,但它不能解决OP每次都没有进行重新计算的问题。你可以缓存它......但是每次'r'改变时你都必须使缓存无效。在这个例子中,我不确定有什么意见... – Ben