除了前面介绍的 while 语句,Python还更多的流程控制工具。
>>> 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语句替代。
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(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(10) 生成了一个包含10个值的链表,但是不包含最右边的值。默认从0开始,也可以让range 从其他值开始,或者指定不同的增量值(甚至是负数,有时也称"步长"):
>>> range(5, 10) [5, 6, 7, 8, 9] >>> range(0, 10, 3) [0, 3, 6, 9] >>> range(-10, -100, -30) [-10, -40, -70] >>> range(-10, -100, 30) []
如果迭代时需要索引和值可结合使用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语句和C中的类似,用于终止当前的for或while循环。
循环可能有else 子句;它在循环迭代完整个列表(对于 for)后或执行条件为false(对于 while)时执行,但循环break时不会执行。这点和try...else而不是if...else相近。请看查找素数的程序:
>>> for n in range(2, 10): ... 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(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
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 = 0, 1 ... 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 = 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]
return语句从函数中返回值,不带表达式的return返回None。过程结束后也会返回 None 。
语句result.append(b)称为调用了列表的方法。方法是属于对象的函数,如obj.methodename,obj 是个对象(可能是一个表达式),methodname是对象的方法名。不同类型有不同的方法。不同类型可能有同名的方法。append()向链表尾部附加元素,等同于 result = result + [b] ,不过更有效。
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] [1, 2] [1, 2, 3]
规避方式:
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(110, voltage=220) # 同一参数重复指定值 parrot(actor='John Cleese') # 不正确的关键字参数名
关键字参数在位置参数之后,多个关键字参数的顺序先后无关,一个参数只能指定一次值,报错实例:
>>> def function(a): ... pass ... >>> function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? 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(3, 6) # normal call with separate arguments [3, 4, 5] >>> args = [3, 6] >>> range(*args) # call with arguments unpacked from a list [3, 4, 5]
同样的字典可以用两个星号解包:
>>> 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 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,推荐使用。
软件自动化测试是利用特殊软件(跟被测软件比较)来控制测试执行并比较实际结果与预测结果。自动化测试可以在测试过程中自动化一些重复性的但必要的任务, 或者增加手工难以执行的额外的测试,比如性能测试、压力测试,模拟测试、接口测试、单元测试等。自动化测试一般具备准备测试环境、测试控制、判断结果和测试报告的功能。
测试框架生成用户界面的事件,如按键和鼠标点击,并观察用户界面的变化结果,以验证该观测到的行为的程序是否正确。
许多测试自动化工具提供的记录和回放功能,让用户能够记录用户的交互行动和重播。这种方法的优点是它需要很少或根本没有软件开发。但是稍有改变,维护工作就比较大。
web测试是GUI的变种,它是阅读的HTML不是观察窗口事件,使用的技术有很大差异。selenium是知名的web测试工具,selenium有python api,参见:https://pypi.python.org/pypi/selenium。
对类,模块或库的公共接口进行测试。一种日益增长的趋势是在软件开发使用的测试框架,如xUnit框架(例如, pytest和unittest)允许代码进行单元测试。
代码驱动的自动化测试是敏捷软件开发的一个重要特点。这种方法的支持者认为,它生产的软件,是更可靠,成本更低。
API测试也被广泛使用,因为GUI的自动化测试的成本太高。
测试开发基于框架或者编程调用应用的接口,比如SNMP,COM,HTTP常用的接口,命令行等。
作者博客:http://my.oschina.net/u/1433482
联系作者:徐荣中 python开发自动化测试群113938272 微博 http://weibo.com/cizhenshi。
python 2.7 英文官方教程:https://docs.python.org/2/tutorial/
英文维基百科自动化测试介绍:https://en.wikipedia.org/wiki/Test_automation