python 2.7 中文教程-4:编程基础

流程控制

除了前面介绍的 while 语句,Python还更多的流程控制工具。

if语句

>>> x = int(raw_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

可能会有零到多个elif部分,else是可选的。关键字‘elif‘是‘else if’的缩写,可避免过深的缩进。 if ... elif ... elif序列用于替代其它语言中的switch或case语句。python中没有case语言,可以考虑用字典或者elif语句替代。

 

for语句

Python的for语句针对序列(列表或字符串等)中的子项进行循环,按它们在序列中的顺序来进行迭代。
 

>>> # Measure some strings:
... words = ['cat''window''defenestrate']
>>> for w in words:
...     print w, len(w)
...
cat 3
window 6
defenestrate 12

在迭代过程中修改迭代序列不安全,可能导致部分元素重复两次,建议先拷贝:
 

>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate''cat''window''defenestrate']

range()函数

内置函数 range()生成等差数值序列:

>>> range(10)
[0123456789]

range(10) 生成了一个包含10个值的链表,但是不包含最右边的值。默认从0开始,也可以让range 从其他值开始,或者指定不同的增量值(甚至是负数,有时也称"步长"):

>>> range(510)
[56789]
>>> range(0103)
[0369]
>>> range(-10, -100, -30)
[-10, -40, -70]
>>> range(-10, -10030)
[]

如果迭代时需要索引和值可结合使用range()和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

不过使用enumerate()更方便,参见后面的介绍。

break和continue语句及循环中的else子句

break语句和C中的类似,用于终止当前的for或while循环。

循环可能有else 子句;它在循环迭代完整个列表(对于 for)后或执行条件为false(对于 while)时执行,但循环break时不会执行。这点和try...else而不是if...else相近。请看查找素数的程序:
 

>>> for n in range(210):
...     for x in range(2, n):
...         if n % x == 0:
...             print n, 'equals', x, '*', n/x
...             break
...     else:
...         # loop fell through without finding a factor
...         print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

continue语句也是从C而来,它表示退出当次循环,继续执行下次迭代。通常可以用if...else替代,请看查找偶数的实例:
 

>>> for num in range(210):
...     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

pass

pass语句什么也不做。它语法上需要,但是实际什么也不做场合,也常用语以后预留以后扩展。例如:
 

>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...
>>> class MyEmptyClass:
...     pass
...
>>> def initlog(*args):
...     pass   # Remember to implement this!
...

定义函数

菲波那契数列的函数:
 

>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 01
...     while a < n:
...         print a,
...         a, b = b, a+b
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

关键字def引入函数定义,其后有函数名和包含在圆括号中的形式参数。函数体语句从下一行开始,必须缩进的。
函数体的第一行语句可以是可选的字符串文本,即文档字符串。有些工具通过docstrings 自动生成文档,或者让用户通过代码交互浏览;添加文档字符串是个很好的习惯。
函数执行时生成符号表用来存储局部变量。 确切地说,所有函数的变量赋值都存储在局部符号表。 变量查找的顺序,先局部,然后逐级向上,再到全局变量,最后内置名。全局变量可在局部直接饮用,但不能直接赋值(除非用global声明),尽管他们可以被引用, 因为python在局部赋值会重新定义一个本地变量。
函数的实际参数在调用时引入局部符号表,也就是说是传值调用(值总是对象引用, 而不是该对象的值)。
函数定义会在当前符号表内引入函数名。 函数名的值为用户自定义函数的类型,这个值可以赋值给其他变量当做函数别名使用。

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

没有return语句的函数也会返回None。 解释器一般不会显示None,除非用print打印。

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

从函数中返回
 

>>> def fib2(n): # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 01
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[01123581321345589]

return语句从函数中返回值,不带表达式的return返回None。过程结束后也会返回 None 。

语句result.append(b)称为调用了列表的方法。方法是属于对象的函数,如obj.methodename,obj 是个对象(可能是一个表达式),methodname是对象的方法名。不同类型有不同的方法。不同类型可能有同名的方法。append()向链表尾部附加元素,等同于 result = result + [b] ,不过更有效。

深入Python函数定义

python的函数参数有三种方式。

默认参数

最常用的方式是给参数指定默认值,调用时就可以少传参数:
 

def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
    while True:
        ok = raw_input(prompt)
        if ok in ('y''ye''yes'):
            return True
        if ok in ('n''no''nop''nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise IOError('refusenik user')
        print complaint

调用方式:

    只给出必选参数: ask_ok('Do you really want to quit?')
    给出一个可选的参数: ask_ok('OK to overwrite the file?', 2)
    给出所有的参数: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

in关键字测定序列是否包含指定值。

默认值在函数定义时传入,如下所示:
 

i = 5
def f(arg=i):
    print arg
i = 6
f()

上例显示5。

注意: 默认值只赋值一次。当默认值是可变对象(比如列表、字典或者大多数类的实例)时结果会不同。实例:
 

def f(a, L=[]):
    L.append(a)
    return L
print f(1)
print f(2)
print f(3)
执行结果:
[1]
[12]
[123]

规避方式:
 

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

关键字参数


关键字参数 的形式: keyword = value。

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"

有效调用:
 

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million''bereft of life''jump')         # 3 positional arguments
parrot('a thousand'state='pushing up the daisies')  # 1 positional, 1 keyword

无效调用
 

parrot()                     # 没有必选参数
parrot(voltage=5.0, 'dead')  # 关键参数后面有非关键字参数
parrot(110voltage=220)     # 同一参数重复指定值
parrot(actor='John Cleese')  # 不正确的关键字参数名

关键字参数在位置参数之后,多个关键字参数的顺序先后无关,一个参数只能指定一次值,报错实例:
 

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
  File "<stdin>", line 1in ?
TypeError: function() got multiple values for keyword argument 'a'

最后一个如果前有两个星号(比如name)接收一个字典,存储形式参数没有定义的参数名和值。类似的单个星号比如*name表示接受一个元组。
 

def cheeseshop(kind, *arguments, **keywords):
    print "-- Do you have any", kind, "?"
    print "-- I'm sorry, we're all out of", kind
    for arg in arguments:
        print arg
    print "-" * 40
    keys = sorted(keywords.keys())
    for kw in keys:
        print kw, ":", keywords[kw]

调用
 

cheeseshop("Limburger""It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper='Michael Palin',
           client="John Cleese",
           sketch="Cheese Shop Sketch")

执行:
 

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch

注意参数顺序是随机的,可以使用sort排序。

任意参数列表

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

参数列表解包

把列表或元组拆分成多个并列的参数。

>>> range(36)             # normal call with separate arguments
[345]
>>> args = [36]
>>> range(*args)            # call with arguments unpacked from a list
[345]

同样的字典可以用两个星号解包:
 

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print "-- This parrot wouldn't", action,
...     print "if you put", voltage, "volts through it.",
...     print "E's", state, "!"
...
>>> d = {"voltage""four million""state""bleedin' demised""action""VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

 

Lambda表达式

lambda关键字可创建短小的匿名函数,函数体只有一行,创建时就可使用。比如求和:lambda a, b: a+b。通常不建议使用:
 

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

除了返回表达式,lambda还可以用作函数参数。

>>> pairs = [(1'one'), (2'two'), (3'three'), (4'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4'four'), (1'one'), (3'three'), (2'two')](1)

文档字符串

文档字符串的内容和格式建议如下。

第一简短介绍对象的目的。不能描述对象名和类型等其他地方能找到的信息,首字母要大写。
如果文档字符串有多行,第二行为空行以分隔概述和其他描述。描述介绍调用约定、边界效应等。
Python解释器不会从多行文档字符串中去除缩进,要用工具来处理。约定如下:第一行后的第一个非空行决定了整个文档的缩进。实例:
 

>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn't do anything.
...     """
...     pass
...
>>> print my_function.__doc__
Do nothing, but document it.
    No, really, it doesn't do anything.

编码风格


建议遵守PEP8,高可读性,部分要点如下:

    使用4空格缩进,而非tab。
    每行不超过79个字符。
    使用空行分隔函数和类,以及函数中的大代码块。
    可能的话,注释占一行
    使用文档字符串
    操作符前后有空格,逗号后有空格,但是括号两侧无空格。如: a = f(1, 2) + g(3, 4) 。
    统一函数和类命名。类名用首字母大写的驼峰式,比如CamelCase。函数和方法名用小写和下划线组成:lower_case_with_underscores。类中使用self。
    国际化时不要使用花哨的编码。

另: https://pypi.python.org/pypi/autopep8能把代码调整为符合pep8,https://pypi.python.org/pypi/pep8能检查是否符合pep8,推荐使用。

发布了28 篇原创文章 · 获赞 21 · 访问量 16万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章