如何避免温度脚本中的全局变量?

时间:2016-01-26 19:41:52

标签: python

我已经编写了以下代码来检索openweathermap的当前温度 ,当连接失败时,它应该返回先前的温度。

一切正常,但我想避免使用全局变量 last_temperature 保存以前检索到的温度,我该怎么做?

import time    
from pyowm import OWM

API_key="**********************************"
owm=OWM(API_key)
last_temperature= 15.0

def getcurrentTemperature(city_id): # Gent is 2797656
    global last_temperature 
    try:
        obs = owm.weather_at_id(city_id) #by ID
        w = obs.get_weather()
        temps=w.get_temperature(unit='celsius')
        last_temperature = round(temps['temp'],1)
        return last_temperature
    except:
        return last_temperature

while 1 :
    print getcurrentTemperature(2797656)
    time.sleep(30)

4 个答案:

答案 0 :(得分:1)

您有几种设计选择:

  • 您可以使用static_var,如下所述:What is the Python equivalent of static variables inside a function?
  • 您可以使用last_temperature作为类成员实现一个类。然后,使用代码将负责创建和保存类实例。
  • 或者用户2233706描述的选项(将last_temperature作为getcurrentTemperature的函数参数提供)

我会避免全局变量以及static_var方法,因为它们都对应于静态。例如,在创建单元测试时,您始终必须保持此状态的设置和清理,以避免测试之间的交叉依赖性。

答案 1 :(得分:0)

正如user2233706所说,您只需将last_temperature作为参数传递给getcurrentTemperature()

您还可以跳过返回tryexcept的温度,然后计算温度,然后将其返回finally

import time    
from pyowm import OWM

API_key="**********************************"
owm=OWM(API_key)
last_temperature = 15.0

def getcurrentTemperature(city_id, last_temperature): # Gent is 2797656
    try:
        # If it works it will set the temperature
        obs = owm.weather_at_id(city_id) # by ID
        w = obs.get_weather()
        temps=w.get_temperature(unit='celsius')
        temperature = round(temps['temp'],1)
    except:
        # If it doesn't then simply set the return value to the current temperature
        temperature = last_temperature
    finally:
        # You don't need to include the return in both places - this will be run either way
        return temperature

while 1 :
    current_temperature = getcurrentTemperature(2797656, last_temperature) # Get the current temp
    print current_temperature
    last_temperature = current_temperature # Now set the last temperature to the current one and repeat
    time.sleep(30)

如果这令人困惑或不清楚,请告诉我。

答案 2 :(得分:0)

我假设您在代码的其他部分使用它,否则它没有多大意义。

对我来说,最合乎逻辑的方法是创建一个这样的类:

class TemperatureData:
    def __init__(self, *args, **kwargs):
        self.temperature = 15.0

    def update(self, city_id):
        try:
            temperature = own.weather_at_id(city_id).get_weather().get_temperature(unit='celsius')
            self.temperature = round(temperature['temp'], 1)
        except:
            # please catch only the necessary exceptions, not all of them at once, otherwise you might jsut miss important issues on your code 
            pass

def get_temperature(self):
    return self.temperature

然后你可以创建一个TemperatureData对象(或几个,这很好),并更新它们。您甚至可以自定义get_temperature函数,例如对温度进行编码,或者将其置于开尔文中。

答案 3 :(得分:0)

正如我在评论中提到的,你可以使last_temperature成为你的函数的一个属性并返回它。

def getcurrentTemperature(city_id):
    try:
        # try to compute last_temperature
        getcurrentTemperature.last_temperature = last_temperature
    except SomeException: # you should be more specific here!
        pass

    return getcurrentTemperature.last_temperature

getcurrentTemperature.last_temperature = None

具有愚蠢功能的演示:

>>> def foo(number):
...     try:
...         foo.last_result = int(number)
...     except ValueError:
...         pass
...     return foo.last_result
... 
>>> foo.last_result = None
>>> 
>>> foo(10)
10
>>> foo(23.5)
23
>>> foo('hi')
23
>>> foo('test')
23
>>> foo(11.11)
11