如何处理模块中的全局变量?

时间:2014-12-31 01:00:50

标签: python function global-variables python-import

我尝试对OpenWeatherMap进行非阻止api调用,但我的问题是:

当我对文件进行测试并运行时,global api生效,但导入该函数时,global不再工作,api dident更改: api = ""

在声明我放置global api的函数之后,当我使用print 'The API link is: ' + api时,我得到了确切的api,但global dident生效了!

以下是代码:https://github.com/abdelouahabb/tornadowm/blob/master/tornadowm.py#L62

我做错了什么?

导入文件时:

from tornadowm import *
forecast('daily', q='london', lang='fr')
The API link is: http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london
api
Out[5]: ''

执行文件而不是导入文件时:

runfile('C:/Python27/Lib/site-packages/tornadowm.py', wdir='C:/Python27/Lib/site-packages')

forecast('daily', q='london', lang='fr')
The API link is: http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london

api
Out[8]: 'http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london'

编辑:这是代码,如果Git得到更新:

from tornado.httpclient import AsyncHTTPClient
import json
import xml.etree.ElementTree as ET

http_client = AsyncHTTPClient()
url = ''
response = ''
args = []
link = 'http://api.openweathermap.org/data/2.5/'
api = ''
result = {}
way = ''


def forecast(way, **kwargs):
    global api
    if way in ('weather', 'forecast', 'daily', 'find'):
        if way == 'daily':
            way = 'forecast/daily?'
        else:
            way += '?'
        for i, j in kwargs.iteritems():
            args.append('&{0}={1}'.format(i, j))
        a = ''.join(set(args))
        api = (link + way + a.replace(' ', '+')).replace('?&', '?')
        print 'The API link is: ' + api

        def handle_request(resp):
            global response
            if resp.error:
                print "Error:", resp.error
            else:
                response = resp.body

        http_client.fetch(api, handle_request)
    else:
        print "please put a way: 'weather', 'forecast', 'daily', 'find' "


def get_result():
    global result
    if response.startswith('{'):
        print 'the result is JSON, stored in the variable result'
        result = json.loads(response)

    elif response.startswith('<'):
        print 'the result is XML, parse the result variable to work on the nodes,'
        print 'or, use response to see the raw result'
        result = ET.fromstring(response)

    else:
        print '''Sorry, no valid response, or you used a parameter that is not compatible with the way!\n please check http://www.openweathermap.com/api for more informations''

3 个答案:

答案 0 :(得分:3)

这是使用global的副作用。

from tornadowm import * forecast()你的api函数出现时,我们可以说是“自己”,并且不再与你的全球空间“硬链接”了。

为什么呢?因为您对全局api = ""所做的任何效果都会以您的函数“结束”,并且全局空间中from something import *的定义将优先。

另外,作为旁注,使用from tornadowm import forecast并不是一个好习惯。您应该import tornadown甚至更好,tornadowm.forecast(),然后使用forecast()

更好的是,我只是注意到你的function函数没有返回任何内容。从技术上讲,它不再是procedure,而是global(一个过程就像一个函数,但它什么都不返回,它只是“做”的东西)。

您应该在此函数中定义api,然后在其中定义return api,而不是使用def forecast(blablabla): api = "something" blablabla return api 。像这样:

import tornadowm
api = tornadown.forecast(something)

然后

{{1}}

你已经完成了。

答案 1 :(得分:2)

全局只对其定义的模块是全球性的。因此,通常情况下,当您致电tornadowm.api而不是forecast时,您希望更改api一些其他命名空间。

import *有助于您理解问题。这会将api(以及其他名称)导入导入命名空间。这意味着apitornadowm.api最初指向同一个对象。但是这两个名称没有以任何方式链接,因此调用forecast()仅更改tornadowm.api,现在这两个名称指向不同的对象。

为避免这种情况,请勿使用import *。无论如何这都是不好的做法,这只是其中一个原因。而是import tornadowm并将导入模块中的变量作为tornadowm.api访问。

答案 2 :(得分:1)

我担心这是因为全局与模块内耦合,当您from tornadowm import *导入api名称时, global api 不会在另一个模块中采取任何效果。