Python学习笔记(五)

"Python学习笔记"

Posted by jhljx on August 29, 2017

目录

1. Python list操作
1.1 extend方法、append方法、’+’、’+=’的区别
2. Python不支持函数重载
3. Python2 str与unicode
3.1 Python2 str与unicode的声明与转换
3.2 设置默认编码
3.3 文件头声明编码
3.4 Python2中如何防止乱码
4. Python2 urllib/urllb2的使用
4.1 Python2 urllib/urllib2如何get和post数据
4.2 urllib2添加headers
4.3 urllib库urlencode,unquote等函数用法
4.4 Python2 urllib2参数中含有中文
4.5 Python2 urllib2获得的内容乱码
5. Python显示json数据中的中文
6. Python with语句
7. Python作用域规则与命名空间
8. Python global关键字和nonlocal关键字
9. Reference

Python list操作

extend方法、append方法、’+’、’+=’的区别

python中extend和append方法都是list的方法,其中list列表可以包含任何数据类型的元素,单个列表的元素无须全为同一种类型。

extend方法只接受一个列表作为参数,并将该参数中的每一个元素都添加到原有列表中。
append方法向list末尾添加一个新的元素,但是也是只接受一个参数,并且将这个参数直接添加到列表末尾。

注意以下几点:

  • append和extend方法都只接受一个参数,append方法的参数任意,可以为列表,也可以为字典,元组。
  • extend方法只能接受列表作为参数。
  • ”+” 直接用+号看上去与用extend()一样的效果,但是实际上是生成了一个新的列表存这两个列表的和,只能用在两个列表相加上
  • ”+=” 效果与extend()一样,向原列表追加一个新元素,在原有列表上增加

例子如下:

>>> myList = [1, 2.0, 'a']
>>> myList
[1, 2.0, 'a']
>>> myList.append('APP')
>>> myList
[1, 2.0, 'a', 'APP']
>>> myList.extend([123, 'abc'])
>>> myList
[1, 2.0, 'a', 'APP', 123, 'abc']
>>> myList.append([1,2,3])
>>> myList
[1, 2.0, 'a', 'APP', 123, 'abc', [1, 2, 3]]
>>> myList.append({'a':1, 'b':2, 'c':3})
>>> myList
[1, 2.0, 'a', 'APP', 123, 'abc', [1, 2, 3], {'a':1, 'b':2, 'c':3}]
>>> myList.append((1,2,3)))
>>> myList
[1, 2.0, 'a', 'APP', 123, 'abc', [1, 2, 3], {'a':1, 'b':2, 'c':3}, (1, 2, 3)]
>>> A = [1,2,3]
>>> B = [4,5,6]
>>> C = A + B
>>> C
[1, 2, 3, 4, 5, 6]
>>> A += B
>>> A
[1, 2, 3, 4, 5, 6]

Python不支持函数重载

函数重载主要是为了解决两个问题。

  1. 可变参数类型。
  2. 可变参数个数。

另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。

好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。

那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。

好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。

作者:pansz
链接:https://www.zhihu.com/question/20053359/answer/14054112
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Python2 str与unicode

Python2 str与unicode的声明与转换

声明unicode字符串的方法有以下两种:

s1 = u'人生苦短,我学Python'
s2 = unicode('人生苦短', 'utf-8')

关于str与unicode的转换,unicode转str需要encode,str转unicode需要decode。

# -*- coding:utf-8 -*-
su = "人生苦短"
# : su是一个utf-8格式的字节串
u  = s.decode("utf-8")
# : s被解码为unicode对象,赋给u
sg = u.encode("gbk")
# : u被编码为gbk格式的字节串,赋给sg
print sg
# 打印sg

但是str也有encode函数,如下例:

s = "人生苦短"
s.encode('gbk') # 相当于s.decode('ascii').encode('gbk')

实际上,当对str进行编码时,会先用默认编码将自己解码为unicode,然后在将unicode编码为你指定编码。
这就引出了python2.x中在处理中文时,大多数出现错误的原因所在:python的默认编码,defaultencoding是ascii。
所以上面的代码会报错UnicodeDecodeError: ‘ascii’ codec can’t decode byte ……

设置默认编码

设置defaultencoding的代码如下:

reload(sys)
sys.setdefaultencoding('utf-8')

如果你在python中进行编码和解码的时候,不指定编码方式,那么python就会使用defaultencoding。
所以,有以下结论成立:

s.encode(“utf-8”) 等价于 s.decode(defaultencoding).encode(“utf-8”) u = unicode(“人生苦短”) 等价于 u = unicode(“人生苦短”,defaultencoding)

文件头声明编码

顶部的:# -- coding: utf-8 --目前看来有三个作用。

  • 如果代码中有中文注释,就需要此声明
  • 比较高级的编辑器(比如我的emacs),会根据头部声明,将此作为代码文件的格式。
  • 程序会通过头部声明,解码初始化 u”人生苦短”,这样的unicode对象,(所以头部声明和代码的存储格式要一致)

关于requests库

requests是一个很实用的Python HTTP客户端库,编写爬虫和测试服务器响应数据时经常会用到。

其中的Request对象在访问服务器后会返回一个Response对象,这个对象将返回的Http响应字节码保存到content属性中。

但是如果你访问另一个属性text时,会返回一个unicode对象,乱码问题就会常常发成在这里。

因为Response对象会通过另一个属性encoding来将字节码编码成unicode,而这个encoding属性居然是responses自己猜出来的。

官方文档:

text Content of the response, in unicode.

If Response.encoding is None, encoding will be guessed using chardet.

The encoding of the response content is determined based solely on HTTP headers, following RFC 2616 to the letter. If you can take advantage of non-HTTP knowledge to make a better guess at the encoding, you should set r.encoding appropriately before accessing this property.

所以要么你直接使用content(字节码),要么记得把encoding设置正确,比如我获取了一段gbk编码的网页,就需要以下方法才能得到正确的unicode。

import requests
url = "http://xxx.xxx.xxx"
response = requests.get(url)
response.encoding = 'gbk'
 
print response.text

Python2中如何防止乱码

基本设置

主动设置defaultencoding。(默认的是ascii)

代码文件的保存格式要与文件头部的# coding:xxx一致

如果是中文,程序内部尽量使用unicode,而不用str

关于打印

你在打印str的时候,实际就是直接将字节流发送给shell。如果你的字节流编码格式与shell的编码格式不相同,就会乱码。

而你在打印unicode的时候,系统自动将其编码为shell的编码格式,是不会出现乱码的。

程序内外要统一

如果说程序内部要保证只用unicode,那么在从外部读如字节流的时候,一定要将这些字节流转化为unicode,在后面的代码中去处理unicode,而不是str。

with open("test.txt", "r") as f:
    for i in f:
        # 将读入的utf-8字节流进行解码
        u = i.decode('utf-8')
        ....

如果把连接程序内外的这段数据流比喻成通道的的话,那么与其将通道开为字节流,读入后进行解码,不如直接将通道开为unicode的。

# 使用codecs直接开unicode通道
file = codecs.open("test", "r", "utf-8")
for i in file:
    print type(i)
    # i的类型是unicode的

##Python2 urllib/urllb2的使用

Python2 urllib/urllib2如何get和post数据

Python2 urllib get/post数据方式:

  • get方式传递数据
#!/usr/bin/python  
#coding=utf-8  
   
import urllib,urllib2  
   
uri = 'http://www.qieke.com/index.php'  
params = {  
'_c': 'user',  
'_m': 'info',  
};  
   
params['user_id']= 123456  
params['user_name'] = '全仔'  
params = urllib.urlencode(params)  
ret = urllib.urlopen("%s?%s"%(uri, params))  
code = ret.getcode()  
ret_data = ret.read()  

需要注意的就是在urlopen函数的使用,get方式是urllib.urlopen("%s?%s"%(uri, params)),而post方式是urllib.urlopen(uri, params)

Python2 urllib2的最基本使用方式如下:

import urllib2   
response = urllib2.urlopen('http://python.org/')   
html = response.read()   

在请求api时,需要使用Request对象来映射你发起的http请求,在它最简单的使用形式中你将用你要请求的地址创建一个Request对象,通过调用urlopen并传入Request对象,将返回一个相关请求response对象,这个应答对象如同一个文件对象,所以你可以在Response中调用.read()。

import urllib2    
req = urllib2.Request('http://www.voidspace.org.uk')   
response = urllib2.urlopen(req)   
the_page = response.read()   

Python2 urllib2 get/post数据使用样例如下:

使用get方式时主要用’?’和urllib.urlencode函数来实现将参数的字典编码为url格式。
使用post方式时常用json.dumps函数将参数的data字典转换为json字符串(如果接受json对象的话),最好不要用urllib.urlencode函数。

  • get方式传递数据
import os,sys  
import os,sys  
import urllib2  
  
http_str = 'http://127.0.0.1:6666/process/' 
data = {'a':'111', 'b': '222', 'c':'333'}
value = urllib.urlencode(data)  #value的结果为a=111&b=222&c=333
url = http_str + '/machine_info?' + value
req = urllib2.Request(url) # url 转换成发起get 请求的url  
result = urllib2.urlopen(req) # 发起GET http服务  
res = result.read() #把结果通过.read()函数读取出来  
slave_info = json.loads(res) #把返回结果(string) 转换成json,方便处理  
print slave_info['content']['slave'] # 打印json 串的dict 信息  
  • post方式传递数据
import os,sys  
import os,sys  
import urllib2  
  
url1 = 'http://127.0.0.1:6666/process/' # url 部分  
params1 = {"app_rpm_id":"-1","rpm_xxx":rpmxxxxx} #参数部分  
params = json.dumps(params1) 
# http 服务器要求传入的params 必须是json 对象,所以这里需要转换一下;
# 如果http 服务器没有要求,就可以不转换  
  
response = urllib.urlopen(url1, params) #发送POST 请求 print response 
# 因为http 服务器已经规定好返回的结果就是一个json 对象,所以不用再转换成json  
print response.read() 
# 把结果数据通过read()读出来;如果http返回的不是json 对象,还需要转换成json 对象

urllib2添加headers

我们也可以给Request添加http头部headers,添加header可以使用以下两种方式。

#方式一
request = urllib2.Request(url, post_data)
request.add_header('Content-Type', 'application/json; charset=UTF-8')
#方式二
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'   
headers = { 'User-Agent' : user_agent }   
request = urllib2.Request(url, post_data, headers)

urllib库urlencode,unquote等函数用法

使用urllib.urlencode时如果有中文最好先把unicode通过encode转化成UTF-8格式的字符串,如果只想对一个字符串进行url编码,使用urllib.quote(string[,safe])即可,safe参数表示不需要编码的字符。还有urllib.quote_plus(string[,safe])函数与urllib.quote类似,但是该函数用’+’来代替’ ‘,而urllib.quote函数用’%20’代替。

使用urllib.unquote(string)函数对字符串进行url解码。urllib.unquote_plus(string)函数类似urllib.unquote函数。但是如果有中文的话,返回的都是默认在gbk下的编码,如果需要utf-8的话,还需要转码。

Python2 urllib2参数中含有中文

需要将中文字符声明成unicode,然后通过unicode内置的encode函数编码成UTF-8格式。详见下面的例子。

access_token = get_token_from_file(token_file_path)
query_sentence = u'帮我查查五道口附近有没有比较好吃,环境比较清静的饭店?'
query_sentence = query_sentence.encode('utf-8')
url = 'https://aip.baidubce.com/rpc/2.0/solution/v1/unit_utterance?access_token=' + access_token
post_data = {"scene_id": scene_id, "query": query_sentence, "session_id": session_id}
post_data = json.dumps(post_data) #这里不能用urllib.urlencode进行url编码,会出现错误! unit错误error_code=282004,请求参数格式不正确
#print(post_data)
request = urllib2.Request(url, post_data)
request.add_header('Content-Type', 'application/json')
response = urllib2.urlopen(request)
content = response.read()
if (content):
    print(content)
content_dict = json.loads(content)

Python2 urllib2获得的内容乱码

可以对返回的data数据解码成‘UTF-8’。

url = "http://www.douban.com"  
#浏览器头  
headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}  
req = urllib2.Request(url=url,headers=headers)  
data = urllib2.urlopen(req).read()  
print data.decode("UTF-8").encode(type)  

Python显示json数据中的中文

Python通过urllib2从服务器获取到response的json数据可能是这个样子的:

'{"no":12,"err_code":220012,"error":null,"data":{"autoMsg":"","fid":6428441,"fname":"\\u884c\\u5c38\\u8d70\\u8089\\u7b2c\\u516d\\u5b63","tid":0,"is_login":1,"content":"","access_state":null,"vcode":{"need_vcode":0,"str_reason":"","captcha_vcode_str":"","captcha_code_type":0,"userstatevcode":0},"is_post_visible":0,"mute_text":null}}'

但是无法显示中文,所以需要将json字符串进行解码,使用的是json字符串的函数json_content.decode('raw_unicode_escape')

比如以下的例子:

result_json = json.dumps(json.loads(content), sort_keys=True,indent=4)
	.decode('raw_unicode_escape')
result_json = result_json.encode('utf-8')

还有一种方法是使用json.dumps()方法,不过需要将设置参数ensure_ascii=False,具体用法如下:

print json.dumps(json.loads(result),ensure_ascii=False)

Python with语句

with语句的基本格式如下:

with context_expression [as target(s)]:
    with-body

这里 context_expression 要返回一个上下文管理器对象,该对象并不赋值给 as 子句中的 target(s) ,如果指定了 as 子句的话,会将上下文管理器的 enter() 方法的返回值赋值给 target(s)。target(s) 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。

with语句可以用来操作文件对象,实例如下:

with open('somefileName', 'r') as somefile:
    for line in somefile:
        print line
        # ...more code

这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄。使用with语句读写文件不用手动close文件,此外可以减少编码量。

with语句的执行过程如下:

context_manager = context_expression
exit = type(context_manager).__exit__  
value = type(context_manager).__enter__(context_manager)
exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
try:  
    try:
        target = value  # 如果使用了 as 子句
        with-body     # 执行 with-body
    except:
        # 执行过程中有异常发生
        exc = False
        # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
        # 由外层代码对异常进行处理
        if not exit(context_manager, *sys.exc_info()):
            raise
finally:
    # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
    # 或者忽略异常退出
    if exc:
        exit(context_manager, None, None, None) 
    # 缺省返回 None,None 在布尔上下文中看做是 False

相关概念:

  • 上下文管理协议(Context Management Protocol):包含方法 enter() 和 exit(),支持该协议的对象要实现这两个方法。

  • 上下文管理器(Context Manager):支持上下文管理协议的对象,这种对象实现了 enter() 和 exit() 方法。上下文管理器定义执行 with语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。

  • 运行时上下文(runtime context):由上下文管理器创建,通过上下文管理器的 enter() 和__exit__() 方法实现,enter() 方法在语句体执行之前进入运行时上下文,exit() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。

  • 上下文表达式(Context Expression):with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。

  • 语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 enter() 方法,执行完语句体之后会执行 exit() 方法。

Python作用域规则与命名空间

作用域简单说就是一个变量的命名空间。代码中变量被赋值的位置,就决定了哪些范围的对象可以访问这个变量,这个范围就是命名空间。python赋值时生成了变量名,当然作用域也包括在内。

在Python中,scope是由namespace按特定的层级结构组合起来的。

scope一定是namespace,但namespace不一定是scope。(scope:作用域,namespace:命名空间)

Python中有四种作用域。

  • Local(innermost): 包含局部变量。比如一个函数/方法内部。
  • Enclosing: 包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,内层函数可能搜索外层函数的namespace,但该namespace对内层函数而言既非局部也非全局。
  • Global(next-to-last): 当前脚本的最外层。比如当前模块的全局变量。
  • Built-in(outtermost): Python builtin 模块。包含了内建的变量/关键字等。

scope的搜索顺序为Local -> Enclosing -> Global -> Built-in,如果逐层查找都没有搜索到,则会抛出NameError异常。

作用域可以嵌套。比如模块导入时。这也是为什么不推荐使用from a_module import *的原因,导入的变量可能被当前模块覆盖

一个丧病的例子:

def outer():
    a = 0
    b = 1
    def inner():
        print a
        print b
        # b += 1        # A
        b = 4           # B
    inner()
outer()

在这个例子中,print b这条语句会报错UnboundLocalError: local variable 'b' referenced before assignment。原因是在inner()函数的作用域中找到了b,但是发现b声明在print之后,导致b变量还未被声明。不管是A还是B哪条语句都会报错。

需要注意两点:

  • 赋值语句通常隐式地会创建一个局部(local)变量,即便该变量名已存在于赋值语句发生的上一层作用域中
  • 如果没有global关键字声明变量,对一个变量的赋值总是认为该变量存在于最内层(innermost)的作用域中;

In Python 2.x, it is not possible to modify a non-local variable; you have either read-only access to a global or non-local variable, or read-write access to a global variable by using the global statement, or read-write access to a local variable (the default).

In Python 3.x, the nonlocal statement has been introduced with a similar effect to global, but for an intermediate scope.

在Python 2.x中,闭包只能读外部函数的变量,而不能改写它。如果要对x进行赋值操作,在Python 2.x中解决这个问题,目前只能使用全局变量:global。 在Python3中增加了nonlocal关键字,使得可以在内层作用域中使用外层作用域中的变量,即nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。

注意,Python与其他编程语言不同(例如C及其后代语言),在函数水平下没有嵌套词法作用域。

以下例子说明Python循环中变量的作用域不仅仅是在循环中。在C++中循环内部的变量为局部变量,作用域只局限于循环内,在循环外并不可以调用。但是Python是不一样的,Python中函数体始终为一个作用域

def foo():
    lst = []
    for i in range(4):
        lst.append(lambda: i)
    print([f() for f in lst])
    #输出结果为[3,3,3,3]

Python中for循环满足以下条件(大坑):

for循环将变量赋值到目标列表中。……当循环结束时,赋值列表中的变量不会被删除,但如果序列是空的,它们将不会被赋值给所有的循环。

说白了就是for 后面跟着的变量(target list)在循环结束后是不会被删除的,但如果 for 循环的序列为空,这些变量是完全不会被赋值的。 这一点Python2和Python3中都一样。

序列为空的例子如下:

for i in []:
    pass
print(i)
#这个例子print的时候会抛出NameError异常。

列表推导式(list comprehension)中的索引变量也泄露到其封闭作用域,或者更准确的说,在Python 3之前可以泄露。Python 3包含许多重大更改,其中也修复了列表推导式中的变量泄露问题。

其他例子:

#块级作用域
if 1 == 1:
    name = "lzl"
print(name)
for i in range(10):
    age = i
print(age)

输出结果为:

lzl
9

这段code可以成功执行说明了以下问题:

Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功
Python中的函数为局部作用域,因此在函数外不能直接访问函数内的局部变量

Python中还有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错。

#作用域链
name = "lzl"
def f1():
    name = "Eric"
    def f2():
        name = "Snor"
        print(name)
    f2()
f1()
print(name)
#输出结果为:
#  Snor
#  lzl

#终极版作用域
name = "lzl"
def f1():
    print(name)
def f2():
    name = "eric"
    f1()
f2()
#输出结果为lzl

#终极版作用域
name = "lzl"
def f1():
    print(name)
def f2():
    name = "eric"
    return f1
ret = f2()
ret()

这里的后两个例子说明了函数f2()中的f1()和return的f1()都保存的是f1在内存中的地址。第三个例子中ret=f2()实质上等价于ret=f1。执行ret()相当于执行f1(),而执行f1()时与f2()没有关系,而不会将f1()函数在f2()函数中展开。

还有一个例子:

li = [lambda :x for x in range(10)]
print(type(li))
print(type(li[0]))
# <class 'list'>
# <class 'function'>
res = li[0]()
print(res)
#输出:9

输出结果是9而不是0,需要记住函数在没有执行(调用)前,内部代码不会执行。 这个地方列表推导式结束后x的值为9,所以当函数再去调用时x都一直是9了。

再看一个关于class的例子:

class A(object):
    a = 3
    b = list(a + i for i in range(10))
# NameError: global name 'a' is not defined

class没有作用域(scope),但有一个局部的名空间(namespace),它并不构成一个作用域。 这意味着在类定义中的表达式可以访问该名空间。

但在类体(class body)中, 对 b 的赋值表达式中,该表达式引入了一个新的作用域,该作用域并不能访问类的名空间。

函数也会引入新的作用域。

class C(object):
    a = 2
    def foo(self):
        return a    # NameError: name 'a' is not defined, use return self.__class__.a

在Python 2中,列表推导式没有引入一个新的作用域

>>> [a for a in range(3)]
[0, 1, 2]
>>> print a
2

而对于Python 2和Python 3,生成器表达式都有引入新的作用域

>>> [a for a in range(3)]
[0, 1, 2]
>>> print(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

解决class中的这个问题有以下几种方案:

  • 用生成器表达式:b = [a + i for i in range(10)]
  • 用函数/lamda表达式引入新的作用域:b = (lambda a: ((a + i for i in range(10))))(a)

附一份访问权限汇总表,如下所示。

list comprehension(列表推导式)的语法如下:

[expression for var in iterable]

generator expressions(生成器表达式)的语法如下:

(expression for var in iterable)
Can access class attributes Python 2 Python 3
list comp. iterable Y Y
list comp. expression Y N
gen expr. iterable Y Y
gen expr. expression N N
dict comp. iterable Y Y
dict comp. expression N N

Python global关键字和nonlocal关键字

在Python 2.x中,闭包只能读外部函数的变量,而不能改写它。如果要对x进行赋值操作,在Python 2.x中解决这个问题,目前只能使用全局变量:global。 在Python3中增加了nonlocal关键字,使得可以在内层作用域中使用外层作用域中的变量,即nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。

gcount = 0 
def global_test():

	gcount+=1
	print (gcount)
global_test()

在global_test 函数中程序会因为“如果内部函数有引用外部函数的同名变量或者全局变量,并且对这个变量有修改.那么python会认为它是一个局部变量,又因为函数中没有gcount的定义和赋值,所以报错。

如果在gcount+=1前面加上global gcount,则会输出1,而不是报错。

事实上,网络上很多文章推崇另外的一种方法来使用全局变量:使用单独的global文件。

方法如下:

1.在同一个文件夹下,新建2个文件: myglobal.py test.py
2.myglobal.py中放置全局变量,内容示例如下:

a = 0  
b = 1  
c = 2  
d = 3 

3.test.py中是测试代码,其中可以使用全局变量

import myglobal  
  
def test():  
    myglobal.a = 100  
  
print 'myglobal a = %d' % myglobal.a  
test()  
print 'after test, myglobal a = %d' % myglobal.a  
#输出结果:
#  myglobal a = 0  
#  after test, myglobal a = 100  

一个官方例子的改版:

#coding:utf-8

def scope_test():
    a = 1
    def do_local():
        a = 12  #这里的a为局部变量
        spam = "local spam" 
        #此函数定义了另外的一个spam字符串变量,并且生命周期只在此函数内。
        #此处的spam和外层的spam是两个变量,如果写出spam = spam + “local spam” 会报错
    def do_nonlocal():  #python2测试可去掉该函数
        nonlocal  spam        #使用外层的spam变量
        spam = "nonlocal spam" 
    def do_global():
        global spam
        global a
        # a += 2  #这里会报错,由于没有global name叫a
        a = 3 
        spam = "global spam"
    
    spam = "test spam"
    do_local()
    print("After local assignmane:", spam)
    print("a=", a)
    #do_nonlocal()
    #print("After nonlocal assignment:",spam)
    do_global()
    print("After global assignment:",spam)
    print("a=", a)

scope_test()
print("In global scope:",spam)
print("a=", a)

输出结果(按照python3)为:

After local assignmane: test spam
a= 1
After global assignment: test spam
a= 1
In global scope: global spam
a= 3

这里需要注意的是在do_global函数中,实际上整个代码并没有全局变量spam和a,通过对这两个变量生成global,然后赋值,相当于创建了两个global变量,所以在函数调用后就可以直接访问这两个全局变量的值了,否则变量就为函数中的局部变量,在函数外是无法访问的。

还有几个例子:

def make_counter(): 
    count = 0 
    def counter(): 
        nonlocal count 
        count += 1 
        return count 
    return counter 
       
def make_counter_test(): 
  mc = make_counter() 
  print(mc())
  print(mc())
  print(mc())
 
make_counter_test()
#输出结果为:
#  1
#  2
#  3

def add_b():
    #global  b
    b = 42
    def do_global():
        nonlocal  b
        b =  10
        print(b)
    do_global()
    print(b)
add_b()
#输出结果为:
#  10
#  10

Reference

http://python.jobbole.com/82494/
http://python.jobbole.com/81244/
http://python.jobbole.com/81274/
http://www.iplaypy.com/jinjie/jj146.html
http://python.jobbole.com/86465/?utm_source=blog.jobbole.com&utm_medium=relatedPosts
http://blog.csdn.net/wangkjs/article/details/47444599
http://blog.csdn.net/diaoxuesong/article/details/42552943