Python 定义在初始化时按顺序计算属性的类的最佳实践
我想定义一个类,它执行以下操作:Python 定义在初始化时按顺序计算属性的类的最佳实践,python,python-decorators,class-properties,Python,Python Decorators,Class Properties,我想定义一个类,它执行以下操作: Class computer(): def __init__(self, x): # compute first the 'helper' properties self.prop1 = self.compute_prop1(x) self.prop2 = self.compute_prop2(x) # then compute the property that depends on 'h
Class computer():
def __init__(self, x):
# compute first the 'helper' properties
self.prop1 = self.compute_prop1(x)
self.prop2 = self.compute_prop2(x)
# then compute the property that depends on 'helpers'
self.prop3 = self.compute_prop3(x)
def compute_prop1(self, x):
return x
def compute_prop2(self, x):
return x*x
def compute_prop3(self, x):
return self.prop1 + self.prop2
然后,当我初始化一个实例时,我会按顺序计算所有属性(首先是helpers,然后是依赖于helpers的所有内容):
然而,我认为编写这段代码有更好的实践,例如使用decorator。你能给我一些提示吗?谢谢大家! 我认为以下是避免冗余的最简单方法
class computer():
定义初始化(self,x):
self.prop\u dict=self.compute\u prop\u dict(x)
定义计算属性(self,x):
prop1=x
prop2=x*x
返回{'prop1':prop1,'prop2':prop2,'prop3':prop1+prop2}
因此,实例化之后出现的任何内容都可以通过prop\u dict
但是正如Brian在评论中所说,这个顺序只是Python 3.7的语言规范,我认为下面是避免冗余的最简单的方法
class computer():
定义初始化(self,x):
self.prop\u dict=self.compute\u prop\u dict(x)
定义计算属性(self,x):
prop1=x
prop2=x*x
返回{'prop1':prop1,'prop2':prop2,'prop3':prop1+prop2}
因此,实例化之后出现的任何内容都可以通过prop\u dict
但正如Brian在评论中所说,此顺序只是Python 3.7的语言规范,这里是使用属性的类(添加了返回每个属性的方法): 就设计而言,我认为这更好,因为:
- 将
存储为实例变量更有意义:使用对象的目的是避免传递变量,尤其是对象本身可以跟踪的变量李>x
- 属性赋值及其相应的计算在每个属性修饰的方法中捆绑在一起:我们永远不必考虑问题是在init方法(定义属性的地方)还是在compute方法(属性计算的逻辑被安排的地方)中
prop3
。如果我们从不访问它,我们就不需要计算它
与您的示例相比,使用属性的一个“坏”副作用是这些属性没有“存储”在任何地方(因此我添加了最后一个方法):
还要注意的是,使用decorator,无论何时访问属性,都会动态计算属性,而不是在init方法中只计算一次。通过这种方式,属性修饰方法的工作方式类似于方法,但访问方式类似于属性(这就是使用它们的全部意义):
作为旁注,您可以使用缓存对其中一个属性的计算,以防计算开销过大。以下是使用属性的类(添加了用于返回每个属性的方法): 就设计而言,我认为这更好,因为:
- 将
存储为实例变量更有意义:使用对象的目的是避免传递变量,尤其是对象本身可以跟踪的变量李>x
- 属性赋值及其相应的计算在每个属性修饰的方法中捆绑在一起:我们永远不必考虑问题是在init方法(定义属性的地方)还是在compute方法(属性计算的逻辑被安排的地方)中
prop3
。如果我们从不访问它,我们就不需要计算它
与您的示例相比,使用属性的一个“坏”副作用是这些属性没有“存储”在任何地方(因此我添加了最后一个方法):
还要注意的是,使用decorator,无论何时访问属性,都会动态计算属性,而不是在init方法中只计算一次。通过这种方式,属性修饰方法的工作方式类似于方法,但访问方式类似于属性(这就是使用它们的全部意义):
作为补充说明,您可以使用缓存这些属性之一的计算,以防计算开销过大。请注意,维护字典的插入顺序只是Python 3.7+的语言规范。如果您使用的是较旧版本的Python,请注意不要依赖于此。如果以后需要
prop1
和prop2
,此代码看起来不错。如果不这样做,您可以在调用时直接使用它们,比如self.prop=self.compute(self.compute\u prop1(x),self.compute\u prop2(x))
或prop1=;prop2=。。。;self.prop=self.compute(prop1,prop2)
(分号应该是换行符,但注释中的代码格式是有限的…)请注意,维护字典的插入顺序只是Python 3.7+的语言规范。如果您使用的是较旧版本的Python,请注意不要依赖于此。如果以后需要prop1
和prop2
,此代码看起来不错。如果不这样做,您可以在调用时直接使用它们,比如self.prop=self.compute(self.compute\u prop1(x),self.compute\u prop2(x))
或prop1=;prop2=。。。;self.prop=self.compute(prop1,prop2)
(分号应该是换行符,但注释中的代码格式是有限的…)
>>> computer = Computer(3)
>>> computer.__dict__
{'prop1': 3, 'prop2': 9, 'prop3': 12}
Class PropertyComputer:
def __init__(self, x):
self._x = x
@property
def prop1(self):
return self._x
@property
def prop2(self):
return self._x * self._x
@property
def prop3(self):
return self.prop1 + self.prop2
def get_props(self):
return self.prop1, self.prop2, self.prop3
c = PropertyComputer(x=2)
c.__dict__ # outputs {'_x': 2}
c = PropertyComputer(x=2)
c.prop1 # outputs 2
c._x = 10
c.prop1 # outputs 10