Python最新官方文档目前没有中文版,我用自已的语言来翻义The Python Tutorial,即意义,不是直义。所以会省略一些我认为不重要的内容,但尽量不跳过任何知识点。请对应The Python Tutoria目录来看这一系列文章。
4.1. if Statements
elif是else if缩写,if语句与COBOL的EVALUATE相似,其中else相当于other。下例4个分支,程序一定走且只走其中一个分支。优先级依次从上到下,前面三个分支如果不满足就一定走最后一个else分支。
>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
... x = 0
... print('Negative changed to zero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More
4.2. for Statements
>>> # for语句对数组做只读操作
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
如下,在for循环内部对数组做读写操作,则会导致死循环。即不停地插入defenestrate数据项。
>>> for w in words:
... if len(w) > 6:
... words.insert(0, w)
...
解决此问题的一个办法就是使用”slice切片“ words[:],切片是原数组的一份copy。
>>> for w in words[:]: # words[:]是words的一个复制品
... if len(w) > 6:
... words.insert(0, w) #修改的是words,而迭代的是words[:]
...
>>> words #所以不会死循环,只会插入一个defenestrate
['defenestrate', 'cat', 'window', 'defenestrate']
4.3. The range() Function
for是按顺序遍历的,但如果想跳跃式的遍历。那么用range()函数就比较合适了。
>>> for i in range(5): #默认0开始,默认步进1。直到5(不包含5)
... print(i)
...
0
1
2
3
4
range(5, 10) #从5开始(而不是从第5个元素开始),直到10(不包含10),默认递进1
5,6,7,8, 9
range(0, 10, 3) #从0开始,直到10(不包含10),递进3
0, 3, 6, 9
range(-10, -100, -30) #从-10开始,直到-100(不包含-100),递进-30
-10, -40, -70
配合len()使用:
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
range()看起来像是一个数列,但其实它是一个对象,这个对象包含了一些可供迭代的元素项。
>>> list(range(5)) #列出range对象里所有的元素
[0, 1, 2, 3, 4]
>>> range(5) #返回一个对象
range(0, 5)
>>>
4.4. break and continue Statements, and else Clauses on Loops
else语句除了可以和if配套使用,还可以和for配合,此时用于循环迭代。当和for配合使用时,for通常有break语句,如果不走break语句则会走else。走break则整个for跳出而结束。
>>> for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0: #取余数
... print(n, 'equals', x, '*', n//x) #//是取商
... break
... else:
... # 整个for(第二个for)走完都没走进break,则会走入else
... print(n, 'is a prime number')
...
2 is a prime number #range(2,2)是空数列,直接走else
3 is a prime number #range(2,3),3%2 !==0,走不进break,走else
4 equals 2 * 2 #range(2,4),4%2 走进break。
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4 #range(2,8),8%2进break,跳出for,后续的8%4没机会走了。
9 equals 3 * 3
continue只是跳出当前这次迭代,继续下一个迭代,并不会跳出整个for循环。
>>> for num in range(2, 10):
... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
4.5. pass Statements
pass什么也不做,有时因为语法要求必须要求你写点什么,但你又什么都不想做。就可以用pass了 例如
>>> while True:
... pass # Busy-wait for keyboard interrupt (Ctrl+C)
...
>>> class MyEmptyClass:
... pass #啥也不干的类
...
>>> def initlog(*args):
... pass # 新程序程序时,暂时没想好怎么写,先用pass空着。
...
4.6. Defining Functions
>>> def fib(n): # 第一行定义函数
... """第二行是用三个单双引号起来的函数功能说明文档"""
... a, b = 0, 1 # 函数正文从第三行开始,而且要缩进
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
>>> # 调用函数
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
函数被调起后,会生成一个symbol table用于保存该函数内的这些变量所对应的值。因此变量的值,首先会在函数内symbol table里查找,然后再到上一级函数的symbol table查找,一级级往上找,接着到global symbol table找,最后到built-in names table。(有点像其他语言的变量的作用域)
>>> fib
<function fib at 10042ed0> #symbol table所在地址
>>> f = fib #fib在稀释器眼中就是用户自定义的函数,可以将fib赋值给其他变量,相当于函数重命名。
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
没有return关键字的函数默认返回None关键字,解释器通常不会将None打印出来。
return不携带表达式,也返回None。
下例return回一个list
>>> def fib2(n): # return Fibonacci series up to n
... """Return a list containing the Fibonacci series up to n."""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a) # see below
... a, b = b, a+b
... return result
...
>>> f100 = fib2(100) # call it
>>> f100 # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
4.7. More on Defining Functions
函数的参数个数是可变的。
4.7.1. Default Argument Values
定义函数时,参数通过=号给默认值,有默认值的参数是可选参数。
def ask_ok(prompt, retries=4, reminder='Please try again!'):
while True:
ok = input(prompt) #input的用法:弹出prompt信息,然后接收用户输入值到ok
if ok in ('y', 'ye', 'yes'): #in的用法
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise ValueError('invalid user response')
print(reminder)
定义函数时,如果参数有=号,=后面接的是变量,那么默认值取的是在定义函数的那时候的变量值。事后变量值改变也不会影响到默认参数值。例如:
i = 5
def f(arg=i):
print(arg)
i = 6
f()会打印5
但有个例外,对于list, dictionary,对象的实例,则:
def f(a, L=[]):
L.append(a)
return L
print(f(1)) [1]
print(f(2)) [1, 2]
print(f(3)) [1, 2, 3]
4.7.2. Keyword Arguments
调用函数时,可以通过=号以键值形式给参数赋值,此时不必按定义函数时参数的顺序赋值。
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")
parrot(action=’VOOOOOM’, voltage=1000000) 这样调用是可以的。
*args 和**kwargs
先来看这个函数,一般习惯test_args_kwargs(1,2,3)调用,结果如下:
def test_args_kwargs(arg1, arg2, arg3):
print ("arg1:", arg1)
print ("arg2:", arg2)
print ("arg3:", arg3)
test_args_kwargs(1,2,3)
arg1: 1
arg2: 2
arg3: 3
但其实有更方便的方法调用:
# first with *args
>>> args = (1, 2, 3) #将参数设置成一个元组变量或数列变量[1,2,3]
>>> test_args_kwargs(*args) #将该变量以*号传入函数并调起
arg1: 1
arg2: 2
arg3: 3
# now with **kwargs:
>>> kwargs = {"arg3": 3, "arg1": 1, "arg2":2} #将参数设置成字典
>>> test_args_kwargs(**kwargs) #再将参数以**形式传入函数调起
arg1: 1
arg2: 2
arg3: 3
相反,定义函数时也可以用*args 和**kwargs,这时参数个数未定,只有调函数时才知道。
*args用于接收所有位置参数,**kwargs用于接收所有键值参数。
定义同一个函数时*args 必须出现在**kwargs之前。
def test_var_args(f_arg, *argv):
print "first normal arg:", f_arg
for arg in argv:
print "another arg through *argv :", arg
test_var_args('yasoob','python','eggs','test')
#结果如下,第一个参数被f_arg捕获,剩下所有的位置参数被*argv获得。
first normal arg: yasoob
another arg through *argv : python
another arg through *argv : eggs
another arg through *argv : test
又如:
def greet_me(**kwargs):
if kwargs is not None:
for key in kwargs:
print (key,kwargs[key])
>>> greet_me(name="yasoob",hello='LZD')
name yasoob
hello LZD
>>> kwargs={'a':1, 'b':2, 'c':3} # 同样,也可以定义及调用函数同时都用\*args 和\**kwargs
>>> greet_me(**kwargs)
a 1
b 2
c 3
4.7.5. Lambda Expressions
lambda 关键字用于定义一个简单的匿名函数,并return这个函数。
lambda a, b: a+b
冒号前面是lambda 将要返回的函数的参数部分的定义,冒号后面是将要返回的函数的return 部分。即相当于返回了如下一个匿名函数。
def noname(a, b):
return a+b
又如:
>>> def make_incrementor(n):
... return lambda x: x + n #返回一个匿名函数,该函数接收一个x参数,并且返回x+n。
... #n则是make_incrementor的参数。
>>> f = make_incrementor(42) #f被赋值为n=42的匿名函数
>>> f(0) #返回x+n x=0,n=42
42
>>> f(1) #返回x+n x=1,n=42
43
4.8. Intermezzo: Coding Style
代码风格:
- 使用四个空格缩进。(可以更多)
- 每行最多79个字符
- 使用空格分隔函数和类,以及函数中的大代码块
- 注释单独写一行
- 在操作符两边和逗号之后加空格, 括号则不用: a = f(1, 2) + g(3, 4)
- 类和函数的命名风格要一致;传统上使用 CamelCase 驼峰风格命名
- 使用UTF-8编码