如何解决如何根据内部状态在两组属性值之间切换?
我有一堂课保存了一些科学数据。根据内部状态,此类的值可以显示为归一化(即无单位)或非归一化。这些值总是以规范化的形式存储,但如果对象设置为非规范化状态,用户可访问的属性(和方法)将给出非规范化的值。这样,类就会显示为非规范化,而无需复制存储的值。
现在我使用 getter 实现了这个。虽然它有效,但它提供了很多重复的结构,我想知道是否有一种更 Pythonic 的方式来管理它而不会使事情过于复杂。
我这样做对吗?有没有更优雅的方式以类似的方式在两组数据之间切换?
class CoolPhysicsData(object):
def __init__(self,lambda0,*args,normed=False):
self.lambda0 = lambda0 # some normalization factor (wavelength of some wave)
self.normalized = normed # user can change this state as he pleases
self._normed_tmin,self._normed_tmax,self._normed_r = self.calculate_stuffs(*args)
...
@property
def tmin(self):
if self.normalized:
return self._normed_tmin
else:
return denormalize(self.lambda0,self._normed_tmin,unit_type="time")
@property
def tmax(self):
if self.normalized:
return self._normed_tmax
else:
return denormalize(self.lambda0,unit_type="time")
@property
def r(self):
if self.normalized:
return self._normed_r
else:
return denormalize(self.lambda0,self._normed_r,unit_type="len")
... # about 15 getters alike these
解决方法
一种方法是避免使用属性,并实现__getattr__
、__setattr__
和__delattr__
。由于您需要知道要反规范化的数量,因此确实无法逃避定义:这些必须在某处手动编码。我会这样做:
class CoolPhysicsData:
def _get_normalization_params(self,value):
# set up how individual properties should be denormalized..
params = {
# 'property_name' : (norm_factor,norm_value,'unit_type')
'tmin': (self.lambda0,self._normed_tmin,'time'),'tmax': (self.lambda0,self._normed_tmax,'r': (self.lambda0,self._normed_r,'len'),}
return params[value]
我会实现__getattr__
这样的东西:
...
def __getattr__(self,value):
# extract the parameters needed
norm_factor,normed_value,unit_type = self._get_normalization_params(f'{value}')
if self.normed:
return normed_value
else:
return self.denormalize(norm_factor,unit_type)
...
请注意,您可能还想编写 __setattr__
和 __delattr__
。
补充一点:dataclasses
可能对您有用。我不确定您的 *args
函数中的 __init__
是否是确切的签名,或者您只是为了示例而进行了简化。如果您有已知参数(无可变参数),则可以轻松将其转换为 dataclass
。
from dataclasses import dataclass,field
@dataclass
class CoolPhysicsData:
lambda0: float
normed: bool = field(default=False)
def __post_init__(self):
# set up some test values for simplicity
# of course you can run custom calculations here..
self._normed_tmin = 1
self._normed_tmax = 2
self._normed_r = 3
def __getattr__(self,value):
norm_factor,unit_type)
# you may want to implement the following methods too:
# def __setattr__(self,name,value):
# # your custom logic here
# ...
# def __delattr__(self,name):
# # your custom logic here
# ...
def denormalize(self,v1,v2,v3):
# just for simplicity
return 5
def _get_normalization_params(self,value):
# setup how individual properties should be denormalized..
params = {
# 'property_name' : (norm_factor,}
return params[value]
它更像pythonic吗?由你来决定。它肯定会减少一些重复,但您引入了更多的复杂性,而且 - 在我看来 - 它更容易出现错误。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。