... 注释
... 输入输出
... 变量
... 缩进
... 布尔型
... 数字
... 字符串
... List,Tuple
... Set
... Dictionary
... 判断
... 循环
... Pass
... 函数
... 模块
语法基础
注释
后面的代码示例中会出现文字说明注释代码含义,所以在最前面讲一下注释:
单行注释:以 # 开始,到行尾,但如果在单引号或双引号之间就是字符串了
>>> #这是一条注释
>>> str = '#This is not a comment'
'#This is not a comment'
多行注释:文件中,可以用'''...'''
或者 """..."""
表示注释,即:三个双引号/单引号开始,到三个双引号/单引号结束,之间的都是注释语句:
实际上,在标准的Python中这其实是一个多行字符串:
这在后面的多行字符串中再讲吧。
输入输出
学习一门语言只用眼睛看是不行的,有些内容以为自己看明白了,合上书一写就漏洞百出,所以必须得动手练习。我们先简单介绍标准输入输出以辅助后面的练习。
输出:print
>>> print('Hello')
Hello
>>> #可以不加括号:
>>> print 'Hello'
Hello
>>> #多个字符串用逗号分隔跟在print后面,会连成一个空格分隔的大串:
>>> print 'Hello', 'World'
Hello World
>>> #可直接打印计算结果:
>>> print 1 + 2
3
>>> #输入变量名直接打印变量值:
>>> i = 3
>>> i
3
>>> s = 'hello'
>>> s
'hello'
输入:raw_input
>>> name = raw_input()
linhl
>>> print name
linhl
>>> #可增加输入提示的参数:
>>> name = raw_input('请输入姓名: ')
请输入姓名: linhl
>>> print name
linhl
变量
Python是一个动态语言,从前面的代码示例可以看出,我们使用变量的时候都没有指定变量类型,直接写 变量名 = ... 。
变量名只能包含字母、数字和下划线,且不能以数字开头。
定义的变量即要为其赋值,使用未赋值的便利会得到错误:
>>> q
Traceback (most recent call last):
File "<pyshell#119>", line 1, in <module>
q
NameError: name 'q' is not defined
在Python Shell中,最后一次打印的表达式会赋给变量 _
:
In interactive mode, the last printed expression is assigned to the variable _. This means that when you are using Python as a desk calculator, it is somewhat easier to continue calculations, for example:
>>> tax = 12.5 / 100 >>> price = 100.50 >>> price * tax 12.5625 >>> price + _ 113.0625 >>> round(_, 2) 113.06
可以进行多变量一次赋值:
>>> x,y,z = 1,2,3
>>> x
1
缩进
Python的代码块是通过冒号和缩进定义的,像是函数,if,for,while等等,都是在冒号分隔后,相同缩进的是其代码体。缩进一般是四格,但也不是硬性规定,一致就行,最好不要用Tab
:
def add(x,y):
return x + y
if __name__ == "__main__":
print add("abcd","hijk")
print add(1,10)
每行语句用回车分隔,不需要封号。
数据类型
关于内置类型的详细说明请见Python标准库的官方文档,下面只做一些基础及常用的介绍:
布尔型
True,False
真值校验
所有对象都可以做真值校验。以下值会被解释器认为是False:
- None
- False
- 数字类型的0:0,0L,0.0,0j
- 空序列:'',(),[]
- 空字典:{}
- 定义了__nonzero__() 或 len() 方法的类的实例,并且方法的返回值是 0 或 False
其它对象都会被认为是True。
布尔操作符
x or y | if x is false, then y, else x | 只有x为False时才会判断y |
x and y | if x is false, then x, else y | True时才会判断y |
not x | if x is false, then True, else False |
注意 or和and返回的不是True或False,而是x或y本身
数字
整数:int, long(L 后缀)
小数:float
复数:complex
对数字进行加减乘除操作时,结果是int还是float,取决于操作数本身的类型,如果两个操作数都是int则结果也是int(向下取整),只要有一个操作数是float结果就是float:
>>> a = 6
>>> b = 2
>>> a/b
3
>>> a = 6.0
>>> a/b
3.0
常用操作符
>>> 17/3.2 # int / float -> float
5.3125
>>> 17//3.2 # // 表示向下取整
5.0
>>> 17%3 # % 取余
2
>>> 8 ** 3 # ** m**n: m的n次方,等价于:pow(m,n)
512
>>> abs(-10) # 绝对值
10
>>> int(1.7) # 转为整形
1
>>> long(1.7) # 转为长整形
1L
>>> float(1) # 转为浮点型
1.0
>>> divmod(11,2) # (x // y, x % y)
(5,1)
>>> max(1,2,3) # 最大值
3
>>> min(1,2,3) # 最小值
1
字符串
定义
字符串用单引号或双引号包括,两者都行,用单/双引号包括时,字符串中出现的单/双引号需要加 转义:
>>> print '"What\'s your name?",he asked.'
"What's your name?",he asked.
>>> print "\"What's your name?\",he asked."
"What's your name?",he asked.
\
表示转义,如要输出\本身而不需要转义,可用\\
,也可在字符串前加 r
表示原样输出。请自行实验:print 'a\b'
print 'a\\b'
print r'a\b'
多行字符串
讲注释的时候有提到多行字符串,多行字符串用 '''...'''
或 """..."""
表示:
>>> str = '''
a
b
c
'''
>>> print str
a
b
c
>>> # 相当于自动加了 \n :
>>> str
'\na\nb\nc\n'
如果打印时不想换行,就加一个\
:
>>> str = '''a
b\
c
'''
>>> print str
a
bc
>>> str
'a\nbc\n'
\
是续行符,一条命令也可以用它来分成多行:
>>> if a == b \
and a > 0 :
print a
else:
print b
连接
可以通过将多个字符串并排进行连接显示,也可以用 +
连接,但是变量和表达式只能用 +
连接:
>>> 'Hello ' 'World' # 等价于 'Hello ' + 'World'
'Hello World'
>>> a = 'Hello '
>>> a + 'World' # 不能写成 a 'World',变量必须用 + 连接
'Hello World'
>>> 'ab' * 3 + 'cd' # * 表示重复,表达式必须用 + 连接
'abababcd'
>>> # 演示一个使用场景:
>>> text = ('Put several strings within parentheses '
'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
格式化
格式化的字符串包括被替换的字段,有以下几种方式:
通过位置替换
>>> '{0},{1}'.format('Hello','World')
'Hello,World'
>>> '{0},{1} {0},{1}'.format('Hello','World') # 参数可多次使用
'Hello,World Hello,World'
通过参数名替换
>>> '{name},{age}'.format(name='linhl',age=34)
'linhl,34'
通过参数的属性替换
>>> class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
def __str__(self):
return 'Point({self.x}, {self.y})'.format(self=self)
>>> str(Point(4,2))
'Point(4, 2)'
通过参数的元素替换
>>> coord = (3, 5)
>>> 'X: {0[0]}; Y: {0[1]}'.format(coord)
'X: 3; Y: 5'
可以在字段后面加 ":" 和格式指令,对值的格式化加以更多控制:
>>> # 设置字段的最小宽度
>>> for x in range(1,5):
print '{0:d} {1:2d} {2:2d}'.format(x, x**2, x**3)
1 1 1
2 4 8
3 9 27
4 16 64
>>> # 设置精度
>>> import math
>>> print 'The value of PI is approximately {0:.3f}.'.format(math.pi)
The value of PI is approximately 3.142.
zfill()
可以向数值字符串左侧添加0:
>>> '123'.zfill(5)
'00123'
>>> '-123'.zfill(5)
'-0123'
>>> '12345'.zfill(5)
'12345'
索引, 分片
>>> word = 'Python'
>>> word[0] # 第一个字母
'P'
>>> word[-1] # 最后一个字母
'n'
>>> word[2:5] # 第三个字母开始到第五个字母,左闭右开,包括2不包括5
'tho'
>>> word[:2] + ',' + word[4:]
'Py,on'
关于字符串更多的内容参见官方文档。
List,Tuple
list(列表)和tuple(元组)都是sequence(序列)。
list :
>>> list = [1,2,3,4]
>>> list[0] = 5 # 可修改
>>> list
[5, 2, 3, 4]
>>> list.append(6) # 向末尾添加一个元素
>>> list
[5, 2, 3, 4, 6]
>>> list.insert(1,0) # 向指定的索引位置添加
>>> list
[5, 0, 2, 3, 4, 6]
>>> list.extend([7, 8, 9]) # 将另外一个list添加到本list的末尾
>>> list
[5, 0, 2, 3, 4, 6, 7, 8, 9]
>>> list + [10,11,12] # 两个list连接
[5, 0, 2, 3, 4, 6, 7, 8, 9, 10, 11 ,12]
>>> 5 in list # 检测某个元素是否在list中
True
>>> 1 in list
False
>>> list.remove(5) # 移除指定元素
>>> list.pop() # 移除最后一个元素,并返回
9
>>> list.pop(1) # 移除指定索引的元素,并返回
2
>>> list
[0, 3, 4, 6, 7, 8]
tuple :
>>> tuple = (1,) #只有一个元素时需要加一个逗号
>>> tuple = (1,2,3,4)
>>> tuple[0] = 5 # 不可修改
Traceback (most recent call last):
File "<pyshell#249>", line 1, in <module>
tuple[0]=5
TypeError: 'tuple' object does not support item assignment
>>> tuple.append(5) # 不可修改
Traceback (most recent call last):
File "<pyshell#252>", line 1, in <module>
tuple.append(5)
AttributeError: 'tuple' object has no attribute 'append'
>>> tuple + (1,2,3)
(1, 2, 3, 4, 1, 2, 3)
tuple没有方法,不能做增删改查。它的速度比list快,当你需要一个常量集(其中的数据不可修改),或者需要频繁遍历一个常量集的时候,请使用tuple。
list和tuple都可以索引和分片,与上面字符串的一致,分片后会得到新的list/tuple。
把列表当堆栈使用
堆栈的特点是“后进先出”,列表所具有的方法可以很容易实现:使用append()
向列表末尾增加元素(向栈顶添加元素),使用pop()
移除列表最后一个元素(释放栈顶的元素)。
>>> stack = [1,2,3]
>>> stack.append(4)
>>> stack.append(5)
>>> stack
[1,2,3,4,5]
>>> stack.pop()
5
>>> stack.pop()
4
>>> stack
[1,2,3]
把列表当队列使用
队列的特点是“先进先出”,用列表实现效率会比较低,因为每次在头部插入或弹出元素时,需要移动列表中的全部元素。这时我们可以使用 collections.deque
:
>>> from collections import deque
>>> queue = deque([1,2,3])
>>> queue.append(4)
>>> queue.append(5)
>>> queue
deque([1,2,3,4,5])
>>> queue.popleft()
1
>>> queue.popleft()
2
>>> queue
deque([3,4,5])
Set
set 是一个无序的、无重复元素的集合,一般用于成员检测及剔除重复的条目。
>>> # 可以使用大括号或set()定义set
>>> a = {1,1,2,2,3}
>>> a
set([1, 2, 3])
>>> a = set([1,1,2,2,3])
>>> a
set([1, 2, 3])
>>> # 只能使用 set() 定义空set,而不能使用 {} , {}定义的是空字典
>>> a = set()
>>> type(a)
<type 'set'>
>>> a = {}
>>> type(a)
<type 'dict'>
Dictionary
dictionary(字典)定义了 key-value 键值对,是无序的。
>>> d = {"name":"linhl","age":34}
>>> d["name"] # 通过key获取value
'linhl'
>>> d["name"] = "LinHaiLu" # 修改key对应的value
>>> d["name"]
'LinHaiLu'
>>> d["gender"] = "female" # 增加key-value
>>> d["gender"]
'female'
>>> d
{'gender': 'female', 'age': 34, 'name': 'LinHaiLu'}
>>> d.keys() # 获取所有键
['gender', 'age', 'name']
>>> "gender" in d # 判断键是否存在
True
>>> del d["gender"] # 删除key-value
>>> d
{'age': 34, 'name': 'LinHaiLu'}
>>> d.clear() # 清空
>>> d
{}
如果一个列表的元素是键值对元组,可以用dict
直接构造成dictionary:
>>> list = [('a',1),('b',2),('c',3)]
>>> dict(list)
{'a': 1, 'c': 3, 'b': 2}
如果使用字符串做key,使用关键字参数更简单:
>>> dict(a=1,b=2,c=3)
{'a': 1, 'c': 3, 'b': 2}
流程控制
判断
>>> x = int(raw_input("Please enter an integer: "))
Please enter an integer: 10
>>> if x > 10 :
print 'large'
elif x < 10:
print 'small'
else:
print 'equal'
equal
这是一个完整的判断语句,如果熟悉C,或者java,或者javascript,是不是有点不适应?条件没有用小括号括起来,只在最后加了冒号;开始结束也没有花括号,难道靠缩进呀?没错,Python为了给大家养成良好的编码习惯,提高代码的可读性,就是用缩进代表块的。大家可以自己试试看,不写缩进或者乱写缩进会出现什么情况。
循环
for
>>> words = ['a','ab','abc','abcd']
>>> for w in words:
print w
a
ab
abc
abcd
不能在循环中修改当前list,如有需要则要对这个list的拷贝进行循环:
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]: # 借用分片得到一个新的list
if len(w) > 6:
words.insert(0, w)
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']
如需遍历数字序列,可以使用range()
:
>>> # range() 自身的用法:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(2,8)
[2, 3, 4, 5, 6, 7]
>>> range(2,10,3) # 设置步长
[2, 5, 8]
>>> # range()配合for循环:
>>> days = ['Mon.','Tues.','Wed.','Thurs.','Fri.','Sat.','Sun.']
>>> for i in range(len(days)):
print i+1,days[i]
1 Mon.
2 Tues.
3 Wed.
4 Thurs.
5 Fri.
6 Sat.
7 Sun.
使用 break
跳出循环,continue
跳过后续步骤进入下一个循环:
>>> for i in range(10):
if i%2 == 0 :
continue
print i
if i > 5:
break
1
3
5
7
对列表循环,索引和对应的值可以使用 enumerate()
得到:
>>> for i,v in enumerate(['a','b','c']):
print '{0} : {1}'.format(i,v)
0 : a
1 : b
2 : c
对字典循环,关键字和对应的值可以使用 iteritems()
得到:
>>> d = dict(a=1,b=2,c=3)
>>> for k,v in d.iteritems():
print '{0} : {1}'.format(k,v)
a : 1
c : 3
b : 2
while
满足条件时不断循环,直到不满足为止:
>>> i = 0
>>> while i < 10:
i = i + 2
>>> print i
10
Pass
pass
代表一个空块,相当于占位,不做任何处理:
>>> for i in range(6):
if i%2 == 0:
pass
else:
print i
1
3
5
还可以用来定义空类:
class MyEmptyClass:
pass
空函数:
def initlog(*args):
pass
函数、模块
函数
函数申明以 def
开始,然后是函数名,参数。参数在小括号中,多个参数用逗号分隔。不需要指定返回值类型,也不需要指定是否有返回值,实际上,每个Python函数都有返回值,如果执行了return
语句就返回指定的值,否则返回None
。
函数申明后的第一个内容,我们一般写一个多行字符串,作为函数的doc string。这块内容从解释器的角度来说不是必须的,但对于好的编码习惯来说是必须的。doc string在运行时可以作为函数的属性(__doc__
);有些IDE把doc string作为上下文文档信息,在输入函数名时显示为工具信息。
以下是一个简单的函数定义以及调用的示例:
# MyFirst.py
def add(x,y):
"""计算x+y
x和y的类型必须一致
"""
return x + y
if __name__ == "__main__":
print add.__doc__
print add("abcd","hijk")
print add(1,10)
这里的if __name__ == "__main__"
语句我们在下面的模块中介绍。
重命名:
>>> a = add
>>> print a(10,20)
30
参数
Python函数的参数使用非常灵活,们通过示例来看:
缺省参数
# 设置参数的缺省值,有缺省值的参数必须跟在无缺省值参数的后面
>>> def showInfo(str1,str2,times1=1,times2=2):
print str1*times1,str2*times2
# 普通调用
>>> showInfo("a","b",2,4)
aa bbbb
# 使用缺省值
>>> showInfo("a","b")
a bb
# 使用一个缺省值
>>> showInfo("a","b",2) # times2取缺省值
aa bb
# 通过关键字参数指定值
>>> showInfo("a","b",times2=4) # times1取缺省值
a bbbb
# 通过关键字参数打乱传参顺序
>>> showInfo(str2="b",str1="a")
a bb
需要注意,缺省值在方法被定义的时候赋值,并且只赋值一次。在使用list、dictionary、类实例作为缺省值时要特别注意:
>>> i = 1
>>> # 定义函数的时候缺省值是1
>>> def f(arg=i):
print arg
>>> i = 2
>>> 虽然变量变了,但是函数的缺省值还是1
>>> f()
1
看看用list做缺省值:
>>> def f(a,L=[]):
L.append(a)
return L
>>> print f(1)
[1]
>>> print f(2)
[1,2]
原理其实就是这样的:
>>> list = []
>>> def f(a,L=list):
L.append(a)
return L
可以这样改进:
>>> def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
>>> f(1)
[1]
>>> f(2)
[2]
可变参数
如果在定义函数时,不知道参数的个数,那么可以用一个以*
为前缀的参数来接收可变数量的参数:
>>> def f(a,b,*c): # c是一个tuple,接收a和b后面所有的值
print a,b,c
>>> f(1,2,3,4,5)
1 2 (3, 4, 5) # 3,4,5作为一个tuple被c接收
>>> f(1,2)
1 2 ()
传递已有的list或tuple可以这样:
>>> list = [6,7,8]
>>> f(1,2,*list) # 在list前面加一个 *
1 2 (6, 7, 8)
>>> f(1,2,list) # 注意区别
1 2 ([6, 7, 8],)
关键字参数
前面有提到关键字参数,也就是可以显式指定参数值赋给哪个形参。我们还可以使用一个以**
为前缀的参数来接收关键字参数:
>>> def f(a,b,**c): # c是一个dictionary,接收a和b后面的关键字参数
print a,b,c
>>> f(1,2)
1 2 {}
>>> f(1,2,x=3,y=4)
1 2 {'y': 4, 'x': 3}
传递已有的dictionary可以这样:
>>> d = {'x':3,'y':4}
>>> f(1,2,**d) # 在d前面加 **
1 2 {'y': 4, 'x': 3}
内置函数
Python有一些常用的内置函数,都在__builtin__
模块下,可以直接使用:
type 返回任意对象的数据类型
>>> type(1)
<type 'int'>
>>> type("a")
<type 'str'>
>>> import MyFirst
>>> type(MyFirst)
<type 'module'>
>>> type(add)
<type 'function'>
str 将数据强制转换为字符串
>>> str(1)
'1'
>>> d = {'a':1,'b':2}
>>> str(d)
"{'a': 1, 'b': 2}"
>>> str(MyFirst)
"<module 'MyFirst' from 'C:\\Users\\hailu\\Desktop\\MyFirst.py'>"
>>> str(add)
'<function add at 0x00000000028A0828>'
>>> str(None)
'None'
dir 返回任意对象的属性和方法列表
>>> dir(1) # int
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> dir("") # 字符串
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> dir({}) # dictionary
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
>>> dir([]) # list
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> dir(()) # tuple
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
>>> dir(MyFirst) # MyFirst 模块
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'add', 'buildConnStr', 'showInfo']
>>> dir(add) # add 函数
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
变量作用域
需要注意一个变量作用域的问题,比如下面的例子,大家认为运行结果会怎样:
# 全局变量
name = 'a'
# 函数
def do_something():
print name
name = 'b'
print name
do_something()
print name
试验一下看结果与自己想的是否一致?
为什么会出现这种情况(UnboundLocalError: local variable 'name' referenced before assignment)?因为在函数中可以访问全局变量,但是不能修改,一旦出现赋值语句,Python会找同名的局部变量,但是找不到,所以抛出了异常。如果一定要在函数中修改全局变量,可以在修改前加一句申明:
...
def do_something():
...
global name # 表明现在访问全局变量
name = 'b'
...
模块
可以把一个Python文件看作一个模块,其中可以定义变量、函数、类,也可以直接写可执行代码语句。但并不是所有的模块都必须是.py文件,像内置模块,它们是用其它语言写的。
使用import
来引用一个模块,这样我们才能使用这个模块中的函数。例如上面讲函数时在MyFirst.py中定义了一个add函数,现在要在另一个模块中使用,需要这样写:
# 将add从MyFirst模块导入到局部命名空间
from MyFirst import add
print add(1,2)
或者:
# 调用方法时必须加上模块名进行限定
# 此种方式可以避免命名冲突
import MyFirst
print MyFirst.add(1,2)
那么Python是怎么找到MyFirst这个模块的呢?原来Python是对sys.path中定义的目录进行搜索的。sys.path是一个list,我们可以查看并修改它:
>>> import sys
>>> sys.path
['C:\\Users\\hailu\\Desktop', 'D:\\Python27\\Lib\\idlelib', 'C:\\Windows\\SYSTEM32\\python27.zip', 'D:\\Python27\\DLLs', 'D:\\Python27\\lib', 'D:\\Python27\\lib\\plat-win', 'D:\\Python27\\lib\\lib-tk', 'D:\\Python27', 'D:\\Python27\\lib\\site-packages']
如果你需要的模块不在sys.path的目录中,可以使用 sys.path.append()
追加目录。
所有模块都有一个内置属性:__name__
。当本模块直接运行时,它是一个缺省值 __main__
,当在其它模块中被import
时,它的值是模块的文件名,不带文件路径和文件扩展名。利用这一特性,我们可以为模块添加测试组件,例如函数一节的示例中,if __name__ == "__main__"
语句,它的作用有点类似于java在每个类中写的Main函数,当本模块独立运行的时候执行,当被其它模块调用时不会执行。这样我们很方便地在编写模块时进行测试。
Package
使用package可以避免命名空间冲突的问题。package就是含有__init__.py文件(可以是空文件)的目录。例如:
E:\MyPython\
test1\
__init__.py
MyFirst.py
test2\
__init__.py
MyFirst.py
test1和test2是两个package,其下有相同名称的module。
>>> import sys
>>> sys.path.append("E:\\MyPython")
>>> import test1.MyFirst
>>> import test2.MyFirst
>>> test1.MyFirst.add(1,2)
__name__ is test1.MyFirst
3
>>> test2.MyFirst.add(1,2)
__name__ is test2.MyFirst
3