问题描述
可能无法按照我想要的方式完成。我正在用python制作class Temperature
。
我想设置一个名为temperature
的属性,并以Kevin,Celsius或Fahrenheit等不同尺度设置或检索其值。
设置温度:
T = Temperature()
T.temperature = 20 # Set temperature to 20ºC
T.temperature('Fahrenheit') = 68 # Set temperature to 68ºF
T.temperature('Kelvin') = 305 # Set temperature to 305K
获取温度:
t = T.temperature # retrieves temperature in Celsius
t = T.temperature('Fahrenheit') # retrieves temperature in Fahrenheit
t = T.temperature('Kelvin') # retrieves temperature in Kelvin
我有这个代码。首先,我尝试使用@property
装饰器,但无法正常工作。然后,我决定使用x=property(x_get,x_set)
class Temperature:
def __init__(self,temperature:float = 0,scale:str = "Celsius"):
# All temperatures will be stored as KELVIN
self._temperature = None
self.set_temperature(temperature,scale)
def get_temperature(self,scale: str = "Celsius"):
converter = {
"Celsius": self._temperature - 273.15,"Fahrenheit": ((self._temperature - 273.15) * 1.8) + 32,"Kelvin": self._temperature
}
value = converter.get(scale)
return value
def set_temperature(self,value: float,scale: str = "Celsius"):
converter = {
"Celsius": value + 273.15,"Fahrenheit": (value - 32) / 1.8 + 273.15,"Kelvin": value
}
self._temperature = converter.get(scale)
if self._temperature < 0 :
self._temperature = None
raise ValueError("Temperature below 0 Kelvin is not possible")
temperature = property(get_temperature,set_temperature)
但是我不能使用建议的语法;尽管使用传统语法似乎是一个好方法。
在不带任何参数的情况下调用属性temperature
或直接获取和设置带有参数的方法时,它可以工作:
>>> T = Temperature(20) # Initialize
>>> T.temperature # Getter
20.0
>>> T.temperature=30 # Setter
>>> T.temperature # Getter
30.0
如果我直接拨打get_temperature
或set_temperature
>>> T.get_temperature("Fahrenheit")
86.0
但是,如果我使用参数调用getter或setter属性,则会引发错误:
T.temperature("Fahrenheit")
Traceback (most recent call last):
File "<input>",line 1,in <module>
TypeError: 'float' object is not callable
或
T.temperature("Kelvin") = 301.15
File "<input>",line 1
SyntaxError: can't assign to function call
T.temperature = 68,'Fahrenheit'
Traceback (most recent call last):
File "<input>",in <module>
File "<input>",line 19,in set_temperature
TypeError: can only concatenate tuple (not "float") to tuple
解决方法
我认为不需要getter和setter,也不需要pythonic ...通过使用getter和setter,您可以将类的属性设为私有,以保护它们免受其他代码的侵害。提供这种保护的Python方法实际上是通过公开引入属性。
以psuedo-java方式设计类,您可以执行以下操作:
class temperature:
def __init__(self.temp):
self.__temp = temp
def get_temp(self):
return self.__temp
def set_temp(self,temp):
self.__temp = temp
并要访问数据,请执行以下操作
>>>temp1 = temperature(135)
>>>temp1.set_temp(14)
>>>temp1.get_temp()
14
但是,设计此类的一种更加Python化的方法是没有getter和setter并使用public属性。
class temperature:
def __init__(self,temp):
self.temp = temp
现在您无需使用getter或setter即可访问相同的属性
>>>temp1 = temperature(14)
>>>temp1.temp
14
即使数据不一定以这种方式封装……也不一定如此。
我意识到这不能解决您对这三个温度范围的担忧,但是可以通过将输入温度指定为某个单位然后使用转换等轻松地解决这个问题。
编辑
来自@Carlo的评论
可以在下面完成pythonic温度类别的操作,假设您指定了开尔文的输入温度单位,否则需要将该类别扩展为包括法氏温度和摄氏温度输入
class temperature():
def __init__(self,temp,unit):
self.temp = temp
self.unit = unit
if self.unit == 'K':
self.temp_k = self.temp
self.temp_c = self.temp_k + 273
self.temp_f = (self.temp_k + 273)*(9/5)+32
else:
raise TypeError("only kelvin accepted as input temperature")
if __name__ == '__main__':
temp1 = temperature(14,'K')
temp2 = temperature(14,'C') # will raise error
访问temp1对象的温度值然后变得简单
>>> temp1.temp_k
14
>>> temp1.temp_c
287
>>> temp1.temp_f
548.6