Python入门

为什么要学习Python

【人生苦短,我用Python】

(1)Python是一种动态的脚本语言,学习成本大大低于Java等编程语言,因此对于我们测试人员来说,如果需要掌握一门语言,Python就是最好的选择;
(2)由于Python有丰富的第三方库,几乎想要的功能,都能找到对应的库,而我们应用这些库的时候,只考虑怎么去使用这些库提供的API而不用考虑怎么去实现,十分的方便;
(3)Python开发效率很高,同样的任务大约是java的10倍,C/C++的10-20倍,当然这个统计来源于一些编程人员的感受,并不是精确的数值,但是也可以看出其开发效率之高。我们测试人员一般都会主要以手工测试为主,因此不可能全职来运用某种语言实现,肯定需要选择效率高的;
(4)Python支持多种系统,linux、mac上都默认安装了Python,windows更不用说,当我们测试需要在各种平台运行脚本的时候,几乎不用考虑跨平台。

基础语法

标识符

  • 第一个字符必须是字母表中字母或下划线 _
  • 标识符的其他的部分由字母、数字和下划线组成。
  • 标识符对大小写敏感。

    注释

    三种方式:

  • 单行注释以 # 开头

  • 多行注释用三个单引号 ''' 将注释括起来
  • 多行注释用三个双引号 """ 将注释括起来

示例代码如下:

  1. #!/usr/bin/python3
  2. # 这是一个注释
  3. '''
  4. 这是多行注释,用三个单引号
  5. 这是多行注释,用三个单引号
  6. 这是多行注释,用三个单引号
  7. '''
  8. """
  9. 这是多行注释,用三个单引号
  10. 这是多行注释,用三个单引号
  11. 这是多行注释,用三个单引号
  12. """

行与缩进

与多数语言的{}不同,在Python中不使用{}作为代码块,而是使用缩进。
缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。实例如下:

  1. if True:
  2. print ("True")
  3. else:
  4. print ("False")

print输出

print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end=””

  1. #!/usr/bin/python3
  2. x="a"
  3. y="b"
  4. # 换行输出
  5. print( x )
  6. print( y )
  7. print('---------')
  8. # 不换行输出
  9. print( x, end=" " )
  10. print( y, end=" " )
  11. print()
  12. #结果
  13. a
  14. b
  15. ---------
  16. a b

变量与函数

变量

变量(Variable)是存放数据值的容器。每个变量都拥有独一无二的名字,通过变量的名字就能找到变量中的数据。
从底层看,程序中的数据最终都要放到内存(内存条)中,变量其实就是这块内存的名字。
和变量相对应的是常量(Constant),它们都是用来“盛装”数据的小箱子,不同的是:变量保存的数据可以被多次修改,而常量一旦保存某个数据之后就不能修改了。
与一些语言(比如C和JAVA)不同,Python是弱类型语言。强类型语言和弱类型语言的区别就在于:强类型语言的变量类型是在变量定义之初就确定了的,不可更改了,而弱类型语言的变量类型可以随时修改。

  1. C:
  2. int a = 1;
  3. a = "1"; // 报错
  4. JAVA:
  5. int a = 1;
  6. a = "1"; // 报错
  7. JAVASCRIPT:
  8. var a = 1;
  9. a = "1"; // 正常
  10. PYTHON:
  11. a = 1
  12. a = "1" // 正常

函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。
在 Python 中,定义函数使用 def 语句。一个函数主要由三部分构成:

  • 函数名
  • 函数参数
  • 函数返回值
    1. def function(arg):
    2. # Do something
    3. return
    我们来分析一下这些代码:
    首先,我们使用def关键字定义了一个函数function,这个函数接受一个参数arg,定义完函数后用一个半角的冒号结束这行。
    最后一行是一个return关键字,表示返回一个值,这里是返回一个空(None)如果用变量接收,将会是一个None。如果不写这行代码,编译将会报错,因为这个函数里什么也没有(注释不算),如果你不想写return,你可以用pass来代替,也表示结束,但是不返回一个值(接收的话还是None)。

    位置参数

    ```python def test(a, b): print a, b

a和b必须按顺序传入

test(1, 2)

  1. <a name="ilEHs"></a>
  2. #### 关键字参数
  3. ```python
  4. def test(a, b):
  5. print a, b
  6. # a和b可以打乱顺序传入
  7. test(b=2, a=1)
  8. # 有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序,以下用法就是错误的
  9. test(b=2, 1)

默认参数

  1. def test(a, b=3):
  2. print a, b
  3. # b可以不传入,使用默认值3
  4. test(a=5)

可变位置参数

  1. def test(a, *args):
  2. # 接收到的args是一个元组tuple
  3. print a, args
  4. test(1, 2, 3)

可变关键字参数

  1. def test(a, **kwargs):
  2. # 接收到的kwargs是一个字典dict
  3. print a, kwargs
  4. test(1, b=2, c=3)

组合使用

  1. def test(a, b=2, *args, **kwargs):
  2. print a, b, args, kwargs
  3. test(1, 2, 3, 4, c=5, d=6)

数据类型

字符串

Python中的字符串用单引号 或双引号 括起来,可以用加号将两个字符串合并,同时使用反斜杠 \ 转义特殊字符。

  1. name = '小明'
  2. age = '18岁'
  3. print('合并字符串:', name + age) # 合并字符串: 小明18岁

格式化字符串:%s

  1. name= "I'm %s." % ('xiaoming')
  2. print(name) # I'm xiaoming.

Python 访问子字符串,可以使用方括号 [] 来截取字符串
image.png

  1. var1 = 'Hello World!'
  2. var2 = "Runoob"
  3. print ("var1[0]: ", var1[0]) # H
  4. print ("var2[1:5]: ", var2[1:5]) # unno

数字

整型

整数英文为 integer 。代码中的整数跟我们平常认识的整数一样,包括正整数、负整数和零,是没有小数点的数字。Python 可以处理任意大小的整数,例如:1100-80800,等等。

浮点型

浮点数的英文名是 float ,是指带小数的数字。

列表

列表(List)是一种有序的集合,可以随时添加和删除其中的元素。列表也可以使用切片,具体用法和上面讲得字符串类似。
常用的列表方法:

index

index 方法用于从列表中找出某个元素的位置,如果有多个相同的元素,则返回第一个元素的位置。
看看例子:

  1. >>> numbers = [1, 2, 3, 4, 5, 5, 7, 8]
  2. >>> numbers.index(5) # 列表有两个 5,返回第一个元素的位置
  3. 4
  4. >>> numbers.index(2)
  5. 1
  6. >>> words = ['hello', 'world', 'you', 'me', 'he']
  7. >>> words.index('me')
  8. 3
  9. >>> words.index('her') # 如果没找到元素,则会抛出异常
  10. Traceback (most recent call last):
  11. File "<stdin>", line 1, in <module>
  12. ValueError: 'her' is not in list

count

count 方法用于统计某个元素在列表中出现的次数。
看看例子:

  1. >>> numbers = [1, 2, 3, 4, 5, 5, 6, 7]
  2. >>> numbers.count(2) # 出现一次
  3. 1
  4. >>> numbers.count(5) # 出现了两次
  5. 2
  6. >>> numbers.count(9) # 没有该元素,返回 0
  7. 0

append

append 方法用于在列表末尾增加新的元素。
看看例子:

  1. >>> numbers = [1, 2, 3, 4, 5, 5, 6, 7]
  2. >>> numbers.append(8) # 增加 8 这个元素
  3. >>> numbers
  4. [1, 2, 3, 4, 5, 5, 6, 7, 8]
  5. >>> numbers.append([9, 10]) # 增加 [9, 10] 这个元素
  6. >>> numbers
  7. [1, 2, 3, 4, 5, 5, 6, 7, 8, [9, 10]]

extend

extend 方法将一个新列表的元素添加到原列表中。
看看例子:

  1. >>> a = [1, 2, 3]
  2. >>> b = [4, 5, 6]
  3. >>> a.extend(b)
  4. >>> a
  5. [1, 2, 3, 4, 5, 6]
  6. >>>
  7. >>> a.extend(3)
  8. Traceback (most recent call last):
  9. File "<stdin>", line 1, in <module>
  10. TypeError: 'int' object is not iterable
  11. >>> a.extend([3])
  12. >>> a
  13. [1, 2, 3, 4, 5, 6, 3]

注意到,虽然 append 和 extend 可接收一个列表作为参数,但是 append 方法是将其作为一个元素添加到列表中,而 extend 则是将新列表的元素逐个添加到原列表中。

insert

insert 方法用于将某个元素添加到某个位置。
看看例子:

  1. >>> numbers = [1, 2, 3, 4, 5, 6]
  2. >>> numbers.insert(3, 9)
  3. >>> numbers
  4. [1, 2, 3, 9, 4, 5, 6]

pop

pop 方法用于移除列表中的一个元素(默认是最后一个),并且返回该元素的值。
看看例子:

  1. >>> numbers = [1, 2, 3, 4, 5, 6]
  2. >>> numbers.pop()
  3. 6
  4. >>> numbers
  5. [1, 2, 3, 4, 5]
  6. >>> numbers.pop(3)
  7. 4
  8. >>> numbers
  9. [1, 2, 3, 5]

remove

remove 方法用于移除列表中的某个匹配元素,如果有多个匹配,则移除第一个。
看看例子:

  1. >>> numbers = [1, 2, 3, 5, 6, 7, 5, 8]
  2. >>> numbers.remove(5) # 有两个 5,移除第 1 个
  3. >>> numbers
  4. [1, 2, 3, 6, 7, 5, 8]
  5. >>> numbers.remove(9) # 没有匹配的元素,抛出异常
  6. Traceback (most recent call last):
  7. File "<stdin>", line 1, in <module>
  8. ValueError: list.remove(x): x not in list

reverse

reverse 方法用于将列表中的元素进行反转。
看看例子:

  1. >>> numbers = [1, 2, 3, 5, 6, 7, 5, 8]
  2. >>> numbers.reverse()
  3. >>> numbers
  4. [8, 5, 7, 6, 5, 3, 2, 1]

sort

sort 方法用于对列表进行排序,注意该方法会改变原来的列表,而不是返回新的排序列表,另外,sort 方法的返回值是空。
看看例子:

  1. >>> a = [4, 3, 6, 8, 9, 1]
  2. >>> b = a.sort()
  3. >>> b == None # 返回值为空
  4. True
  5. >>> a
  6. [1, 3, 4, 6, 8, 9] # 原列表已经发生改变

如果我们不想改变原列表,而是希望返回一个排序后的列表,可以使用 sorted 函数,如下:

  1. >>> a = [4, 3, 6, 8, 9, 1]
  2. >>> b = sorted(a) # 返回一个排序后的列表
  3. >>> a
  4. [4, 3, 6, 8, 9, 1] # 原列表没有改变
  5. >>> b
  6. [1, 3, 4, 6, 8, 9] # 这是对原列表排序后的列表

注意到,不管是 sort 方法还是 sorted 函数,默认排序都是升序排序。如果你想要降序排序,就需要指定排序参数了。比如,对 sort 方法,可以添加一个 reverse 关键字参数,如下:

  1. >>> a = [4, 3, 6, 8, 9, 1]
  2. >>> a.sort(reverse=True) # 反向排序
  3. >>> a
  4. [9, 8, 6, 4, 3, 1]

该参数对 sorted 函数同样适用:

  1. >>> a = [4, 3, 6, 8, 9, 1]
  2. >>> sorted(a, reverse=True)
  3. [9, 8, 6, 4, 3, 1]

除了 reverse 关键字参数,还可以指定 key 关键字参数,它为每个元素创建一个键,然后所有元素按照这个键来排序,比如我们想根据元素的长度来排序:

  1. >>> s = ['ccc', 'a', 'bb', 'dddd']
  2. >>> s.sort(key=len) # 使用 len 作为键函数,根据元素长度排序
  3. >>> s
  4. ['a', 'bb', 'ccc', 'dddd']

另外,我们还可以使用 sorted 进行多列(属性)排序。

  1. >>> students = [
  2. ('john', 'B', 15),
  3. ('jane', 'A', 12),
  4. ('dave', 'B', 10),
  5. ('ethan', 'C', 20),
  6. ('peter', 'B', 20),
  7. ('mike', 'C', 16)
  8. ]
  9. >>>
  10. # 对第 3 列排序 (从小到大)
  11. >>> sorted(students, key=lambda student: student[2])
  12. [('dave', 'B', 10),
  13. ('jane', 'A', 12),
  14. ('john', 'B', 15),
  15. ('mike', 'C', 16),
  16. ('ethan', 'C', 20),
  17. ('peter', 'B', 20)]
  18. # 对第 2 列排序(从小到大),再对第 3 列从大到小排序
  19. >>> sorted(students, key=lambda student: (student[1], -student[2]))
  20. [('jane', 'A', 12),
  21. ('peter', 'B', 20),
  22. ('john', 'B', 15),
  23. ('dave', 'B', 10),
  24. ('ethan', 'C', 20),
  25. ('mike', 'C', 16)]

字符串和元组是不可变的,而列表是可变(mutable)的,可以对它进行随意修改。我们还可以将字符串和元组转换成一个列表,只需使用 list 函数,比如:

  1. >>> s = 'hello'
  2. >>> list(s)
  3. ['h', 'e', 'l', 'l', 'o']
  4. >>> a = (1, 2, 3)
  5. >>> list(a)
  6. [1, 2, 3]

元组

Python 的元组与列表类似,不同之处在于元组的元素不能修改。
元组使用小括号 ( ),列表使用方括号 [ ]
元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

  1. >>> a = (1, 2, 3) # a 是一个元组
  2. >>> a
  3. (1, 2, 3)
  4. >>> a[0] = 6 # 元组是不可变的,不能对它进行赋值操作
  5. Traceback (most recent call last):
  6. File "<stdin>", line 1, in <module>
  7. TypeError: 'tuple' object does not support item assignment

创建一个值的元组需要在值后面再加一个逗号,这个比较特殊,需要牢牢记住:

  1. >>> a = (12,) # 在值后面再加一个逗号
  2. >>> a
  3. (12,)
  4. >>> type(a)
  5. <type 'tuple'>
  6. >>>
  7. >>> b = (12) # 只是使用括号括起来,而没有加逗号,不是元组,本质上是 b = 12
  8. >>> b
  9. 12
  10. >>> type(b)
  11. <type 'int'>

元组也可以对它进行索引、分片等。由于它是不可变的,因此就没有类似列表的 append, extend, sort 等方法。

字典

字典是 Python 中唯一的映射类型,每个元素由键(key)和值(value)构成,键必须是不可变类型,比如数字、字符串和元组。
这里先介绍字典的几个基本操作:

创建字典

字典可以通过下面的方式创建:

  1. >>> d0 = {} # 空字典
  2. >>> d0
  3. {}
  4. >>> d1 = {'name': 'ethan', 'age': 20}
  5. >>> d1
  6. {'age': 20, 'name': 'ethan'}
  7. >>> d1['age'] = 21 # 更新字典
  8. >>> d1
  9. {'age': 21, 'name': 'ethan'}
  10. >>> d2 = dict(name='ethan', age=20) # 使用 dict 函数
  11. >>> d2
  12. {'age': 20, 'name': 'ethan'}
  13. >>> item = [('name', 'ethan'), ('age', 20)]
  14. >>> d3 = dict(item)
  15. >>> d3
  16. {'age': 20, 'name': 'ethan'}

遍历字典

遍历字典有多种方式,这里先介绍一些基本的方式,后文会介绍一些高效的遍历方式。

  1. >>> d = {'name': 'ethan', 'age': 20}
  2. >>> for key in d:
  3. ... print '%s: %s' % (key, d[key])
  4. ...
  5. age: 20
  6. name: ethan
  7. >>> d['name']
  8. 'ethan'
  9. >>> d['age']
  10. 20
  11. >>> for key in d:
  12. ... if key == 'name':
  13. ... del d[key] # 要删除字典的某一项
  14. ...
  15. Traceback (most recent call last):
  16. File "<stdin>", line 1, in <module>
  17. RuntimeError: dictionary changed size during iteration
  18. >>>
  19. >>> for key in d.keys(): # python2 应该使用这种方式, python3 使用 list(d.keys())
  20. ... if key == 'name':
  21. ... del d[key]
  22. ...
  23. >>> d
  24. {'age': 20}

在上面,我们介绍了两种遍历方式:for key in dfor key in d.keys(),如果在遍历的时候,要删除键为 key 的某项,使用第一种方式会抛出 RuntimeError,使用第二种方式则不会。

判断键是否在字典里面

有时,我们需要判断某个键是否在字典里面,这时可以用 in 进行判断,如下:

  1. >>> d = {'name': 'ethan', 'age': 20}
  2. >>> 'name' in d
  3. True
  4. >>> d['score'] # 访问不存在的键,会抛出 KeyError
  5. Traceback (most recent call last):
  6. File "<stdin>", line 1, in <module>
  7. KeyError: 'score'
  8. >>> 'score' in d # 使用 in 判断 key 是否在字典里面
  9. False

字典常用方法

字典有自己的一些操作方法,这里只介绍部分常用的方法:

clear

clear 方法用于清空字典中的所有项,这是个原地操作,所以无返回值(或者说是 None)。
看看例子:

  1. >>> d = {'name': 'ethan', 'age': 20}
  2. >>> rv = d.clear()
  3. >>> d
  4. {}
  5. >>> print rv
  6. None

再看看一个例子:

  1. >>> d1 = {}
  2. >>> d2 = d1
  3. >>> d2['name'] = 'ethan'
  4. >>> d1
  5. {'name': 'ethan'}
  6. >>> d2
  7. {'name': 'ethan'}
  8. >>> d1 = {} # d1 变为空字典
  9. >>> d2
  10. {'name': 'ethan'} # d2 不受影响

在上面,d1 和 d2 最初对应同一个字典,而后我们使用 d1 = {} 使其变成一个空字典,但此时 d2 不受影响。如果希望 d1 变成空字典之后,d2 也变成空字典,则可以使用 clear 方法:

  1. >>> d1 = {}
  2. >>> d2 = d1
  3. >>> d2['name'] = 'ethan'
  4. >>> d1
  5. {'name': 'ethan'}
  6. >>> d2
  7. {'name': 'ethan'}
  8. >>> d1.clear() # d1 清空之后,d2 也为空
  9. >>> d1
  10. {}
  11. >>> d2
  12. {}

copy

copy 方法实现的是浅复制(shallow copy)。它具有以下特点:

  • 对可变对象的修改保持同步;
  • 对不可变对象的修改保持独立;

看看例子:

  1. # name 的值是不可变对象,books 的值是可变对象
  2. >>> d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
  3. >>> d2 = d1.copy()
  4. >>> d2['name'] = 'peter' # d2 对不可变对象的修改不会改变 d1
  5. >>> d2
  6. {'books': ['book1', 'book2', 'book3'], 'name': 'peter'}
  7. >>> d1
  8. {'books': ['book1', 'book2', 'book3'], 'name': 'ethan'}
  9. >>> d2['books'].remove('book2') # d2 对可变对象的修改会影响 d1
  10. >>> d2
  11. {'books': ['book1', 'book3'], 'name': 'peter'}
  12. >>> d1
  13. {'books': ['book1', 'book3'], 'name': 'ethan'}
  14. >>> d1['books'].remove('book3') # d1 对可变对象的修改会影响 d2
  15. >>> d1
  16. {'books': ['book1'], 'name': 'ethan'}
  17. >>> d2
  18. {'books': ['book1'], 'name': 'peter'}

和浅复制对应的是深复制(deep copy),它会创造出一个副本,跟原来的对象没有关系,可以通过 copy 模块的 deepcopy 函数来实现:

  1. >>> from copy import deepcopy
  2. >>> d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}
  3. >>> d2 = deepcopy(d1) # 创造出一个副本
  4. >>>
  5. >>> d2['books'].remove('book2') # 对 d2 的任何修改不会影响到 d1
  6. >>> d2
  7. {'books': ['book1', 'book3'], 'name': 'ethan'}
  8. >>> d1
  9. {'books': ['book1', 'book2', 'book3'], 'name': 'ethan'}
  10. >>>
  11. >>> d1['books'].remove('book3') # 对 d1 的任何修改也不会影响到 d2
  12. >>> d1
  13. {'books': ['book1', 'book2'], 'name': 'ethan'}
  14. >>> d2
  15. {'books': ['book1', 'book3'], 'name': 'ethan'}

get

当我们试图访问字典中不存在的项时会出现 KeyError,但使用 get 就可以避免这个问题。
看看例子:

  1. >>> d = {}
  2. >>> d['name']
  3. Traceback (most recent call last):
  4. File "<stdin>", line 1, in <module>
  5. KeyError: 'name'
  6. >>> print d.get('name')
  7. None
  8. >>> d.get('name', 'ethan') # 'name' 不存在,使用默认值 'ethan'
  9. 'ethan'
  10. >>> d
  11. {}

setdefault

setdefault 方法用于对字典设定键值。使用形式如下:

  1. dict.setdefault(key, default=None)

看看例子:

  1. >>> d = {}
  2. >>> d.setdefault('name', 'ethan') # 返回设定的默认值 'ethan'
  3. 'ethan'
  4. >>> d # d 被更新
  5. {'name': 'ethan'}
  6. >>> d['age'] = 20
  7. >>> d
  8. {'age': 20, 'name': 'ethan'}
  9. >>> d.setdefault('age', 18) # age 已存在,返回已有的值,不会更新字典
  10. 20
  11. >>> d
  12. {'age': 20, 'name': 'ethan'}

可以看到,当键不存在的时候,setdefault 返回设定的默认值并且更新字典。当键存在的时候,会返回已有的值,但不会更新字典。

update

update 方法用于将一个字典添加到原字典,如果存在相同的键则会进行覆盖。
看看例子:

  1. >>> d = {}
  2. >>> d1 = {'name': 'ethan'}
  3. >>> d.update(d1) # 将字典 d1 添加到 d
  4. >>> d
  5. {'name': 'ethan'}
  6. >>> d2 = {'age': 20}
  7. >>> d.update(d2) # 将字典 d2 添加到 d
  8. >>> d
  9. {'age': 20, 'name': 'ethan'}
  10. >>> d3 = {'name': 'michael'} # 将字典 d3 添加到 d,存在相同的 key,则覆盖
  11. >>> d.update(d3)
  12. >>> d
  13. {'age': 20, 'name': 'michael'}

items/iteritems

items 方法将所有的字典项以列表形式返回,这些列表项的每一项都来自于(键,值)。我们也经常使用这个方法来对字典进行遍历。
看看例子:

>>> d = {'name': 'ethan', 'age': 20}
>>> d.items()
[('age', 20), ('name', 'ethan')]
>>> for k, v in d.items():
...     print '%s: %s' % (k, v)
...
age: 20
name: ethan

iteritems 的作用大致相同,但会返回一个迭代器对象而不是列表,同样,我们也可以使用这个方法来对字典进行遍历,而且这也是推荐的做法:

>>> d = {'name': 'ethan', 'age': 20}
>>> d.iteritems()
<dictionary-itemiterator object at 0x109cf2d60>
>>> for k, v in d.iteritems():
...     print '%s: %s' % (k, v)
...
age: 20
name: ethan

keys/iterkeys

keys 方法将字典的键以列表形式返回,iterkeys 则返回针对键的迭代器。
看看例子:

>>> d = {'name': 'ethan', 'age': 20}
>>> d.keys()
['age', 'name']
>>> d.iterkeys()
<dictionary-keyiterator object at 0x1077fad08>

values/itervalues

values 方法将字典的值以列表形式返回,itervalues 则返回针对值的迭代器。
看看例子:

>>> d = {'name': 'ethan', 'age': 20}
>>> d.values()
[20, 'ethan']
>>> d.itervalues()
<dictionary-valueiterator object at 0x10477dd08>

pop

pop 方法用于将某个键值对从字典移除,并返回给定键的值。
看看例子:

>>> d = {'name': 'ethan', 'age': 20}
>>> d.pop('name')
'ethan'
>>> d
{'age': 20}

popitem

popitem 用于随机移除字典中的某个键值对。
看看例子:

>>> d = {'id': 10, 'name': 'ethan', 'age': 20}
>>> d.popitem()
('age', 20)
>>> d
{'id': 10, 'name': 'ethan'}
>>> d.popitem()
('id', 10)
>>> d
{'name': 'ethan'}

对元素为字典的列表排序

事实上,我们很少直接对字典进行排序,而是对元素为字典的列表进行排序。
比如,存在下面的 students 列表,它的元素是字典:

students = [
    {'name': 'john', 'score': 'B', 'age': 15},
    {'name': 'jane', 'score': 'A', 'age': 12},
    {'name': 'dave', 'score': 'B', 'age': 10},
    {'name': 'ethan', 'score': 'C', 'age': 20},
    {'name': 'peter', 'score': 'B', 'age': 20},
    {'name': 'mike', 'score': 'C', 'age': 16}
]
  • 按 score 从小到大排序

    >>> sorted(students, key=lambda stu: stu['score'])
    [{'age': 12, 'name': 'jane', 'score': 'A'},
    {'age': 15, 'name': 'john', 'score': 'B'},
    {'age': 10, 'name': 'dave', 'score': 'B'},
    {'age': 20, 'name': 'peter', 'score': 'B'},
    {'age': 20, 'name': 'ethan', 'score': 'C'},
    {'age': 16, 'name': 'mike', 'score': 'C'}]
    

    需要注意的是,这里是按照字母的 ascii 大小排序的,所以 score 从小到大,即从 ‘A’ 到 ‘C’。

  • 按 score 从大到小排序

    >>> sorted(students, key=lambda stu: stu['score'], reverse=True)  # reverse 参数
    [{'age': 20, 'name': 'ethan', 'score': 'C'},
    {'age': 16, 'name': 'mike', 'score': 'C'},
    {'age': 15, 'name': 'john', 'score': 'B'},
    {'age': 10, 'name': 'dave', 'score': 'B'},
    {'age': 20, 'name': 'peter', 'score': 'B'},
    {'age': 12, 'name': 'jane', 'score': 'A'}]
    
  • 按 score 从小到大,再按 age 从小到大

    >>> sorted(students, key=lambda stu: (stu['score'], stu['age']))
    [{'age': 12, 'name': 'jane', 'score': 'A'},
    {'age': 10, 'name': 'dave', 'score': 'B'},
    {'age': 15, 'name': 'john', 'score': 'B'},
    {'age': 20, 'name': 'peter', 'score': 'B'},
    {'age': 16, 'name': 'mike', 'score': 'C'},
    {'age': 20, 'name': 'ethan', 'score': 'C'}]
    
  • 按 score 从小到大,再按 age 从大到小

    >>> sorted(students, key=lambda stu: (stu['score'], -stu['age']))
    [{'age': 12, 'name': 'jane', 'score': 'A'},
    {'age': 20, 'name': 'peter', 'score': 'B'},
    {'age': 15, 'name': 'john', 'score': 'B'},
    {'age': 10, 'name': 'dave', 'score': 'B'},
    {'age': 20, 'name': 'ethan', 'score': 'C'},
    {'age': 16, 'name': 'mike', 'score': 'C'}]
    

    集合

    集合(set)和字典(dict)类似,它是一组 key 的集合,但不存储 value。集合的特性就是:key 不能重复。
    先看下集合的常见操作:

    创建集合

    set 的创建可以使用 {} 也可以使用 set 函数:

    >>> s1 = {'a', 'b', 'c', 'a', 'd', 'b'}   # 使用 {}
    >>> s1
    set(['a', 'c', 'b', 'd'])
    >>>
    >>> s2 = set('helloworld')                # 使用 set(),接收一个字符串
    >>> s2
    set(['e', 'd', 'h', 'l', 'o', 'r', 'w'])
    >>>
    >>> s3 = set(['.mp3', '.mp4', '.rmvb', '.mkv', '.mp3'])   # 使用 set(),接收一个列表
    >>> s3
    set(['.mp3', '.mkv', '.rmvb', '.mp4'])
    

    遍历集合

    >>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
    >>> for e in s:
    ...     print e
    ...
    a
    c
    b
    d
    

    添加元素

    add() 方法可以将元素添加到 set 中,可以重复添加,但没有效果。

    >>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
    >>> s
    set(['a', 'c', 'b', 'd'])
    >>> s.add('e')
    >>> s
    set(['a', 'c', 'b', 'e', 'd'])
    >>> s.add('a')
    >>> s
    set(['a', 'c', 'b', 'e', 'd'])
    >>> s.add(4)
    >>> s
    set(['a', 'c', 'b', 4, 'd', 'e'])
    

    删除元素

    remove() 方法可以删除集合中的元素, 但是删除不存在的元素,会抛出 KeyError,可改用 discard()
    看看例子:

    >>> s = {'a', 'b', 'c', 'a', 'd', 'b'}
    >>> s
    set(['a', 'c', 'b', 'd'])
    >>> s.remove('a')           # 删除元素 'a'
    >>> s
    set(['c', 'b', 'd'])
    >>> s.remove('e')           # 删除不存在的元素,会抛出 KeyError
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    KeyError: 'e'
    >>> s.discard('e')          # 删除不存在的元素, 不会抛出 KeyError
    

    交集/并集/差集

    Python 中的集合也可以看成是数学意义上的无序和无重复元素的集合,因此,我们可以对两个集合作交集、并集等。
    看看例子:

    >>> s1 = {1, 2, 3, 4, 5, 6}
    >>> s2 = {3, 6, 9, 10, 12}
    >>> s3 = {2, 3, 4}
    >>> s1 & s2            # 交集
    set([3, 6])
    >>> s1 | s2            # 并集
    set([1, 2, 3, 4, 5, 6, 9, 10, 12])
    >>> s1 - s2            # 差集
    set([1, 2, 4, 5])
    >>> s3.issubset(s1)    # s3 是否是 s1 的子集
    True
    >>> s3.issubset(s2)    # s3 是否是 s2 的子集
    False
    >>> s1.issuperset(s3)  # s1 是否是 s3 的超集
    True
    >>> s1.issuperset(s2)  # s1 是否是 s2 的超集
    False
    

    运算符

    Python 中的运算符主要分为算术运算符、比较(关系)运算符、赋值运算符、逻辑运算符、位运算符、成员运算符和身份运算符共 7 大类,运算符之间也是由优先级的,下面我们就来进行具体介绍。

    算术运算符

    Python 的算术运算符

运算符 描述
+ 两个数相加,或是字符串连接
- 两个数相减
* 两个数相乘,或是返回一个重复若干次的字符串
/ 两个数相除,结果为浮点数(小数)
// 两个数相除,结果为向下取整的整数
% 取模,返回两个数相除的余数
** 幂运算,返回乘方结果

算术运算符使用频率很高,附一张直观的图:
Python入门以及在自动化中的使用 - 图2
以上算术运算符的示例和运行结果如下所示:
>>> 5 + 4
9
>>> 4.3 - 2
2.3
>>> 3 7
21
>>> 2 / 4
0.5
>>> 2 // 4
0
>>> 17 % 3
2
>>> 2 *
5
32

比较(关系)运算符

Python 的比较(关系)算术运算符

运算符 描述
== 比较两个对象是否相等
!= 比较两个对象是否不相等
> 大小比较,例如 x>y 将比较 x 和 y 的大小,如 x 比 y 大,返回 True,否则返回 False
< 大小比较,例如 x<y 将比较 x 和 y 的大小,如 x 比 y 小,返回T rue,否则返回 False
>= 大小比较,例如 x>=y 将比较 x 和 y 的大小,如 x 大于等于 y,返回 True,否则返回 False
<= 大小比较,例如 x<=y 将比较 x 和 y 的大小,如 x 小于等于 y,返回 True,否则返回 False

上述比较(关系)运算符的示例如下所示:
>>> a =1
>>> b =2
>>> print(a == b)
False
>>> print(a != b)
True
>>> print(a > b)
False
>>> print(a < b)
True
>>> print(a >= b)
False
>>> print(a <= b)
True

赋值运算符

Python 的赋值运算符

运算符 描述
= 常规赋值运算符,将运算结果赋值给变量
+= 加法赋值运算符,例如 a+=b 等效于 a=a+b
-= 减法赋值运算符,例如 a-=b 等效于 a=a-b
*= 乘法赋值运算符,例如 a=b 等效于 a=ab
/= 除法赋值运算符,例如 a/=b 等效于 a=a/b
%= 取模赋值运算符,例如 a%=b 等效于 a=a%b
**= 幂运算赋值运算符,例如 a=b等效于 a=ab
//= 取整除赋值运算符,例如 a//=b 等效于 a=a//b

上述赋值运算符的示例如下所示:
>>> a =2
>>> b =3
>>> a+=b
>>> print(a)
5
>>> a-=b
>>> print(a)
2
>>> a=b
>>> print(a)
6
>>> a/=b
>>> print(a)
2.0
>>> a%=b
>>> print(a)
2.0
>>> a*
=b
>>> print(a)
8.0
>>> a//=b
>>> print(a)
2.0

逻辑运算符

Python 的逻辑运算符

运算符 描述
and 布尔“与”运算符,返回两个变量“与”运算的结果
or 布尔“或”运算符,返回两个变量“或”运算的结果
not 布尔“非”运算符,返回对变量“非”运算的结果

上述逻辑运算符的示例如下所示:
>>> a =True
>>> b =False
>>> print(a and b)
False
>>> print(a or b)
True
>>> print(not(a and b))
True

位运算符

Python 的位运算符

运算符 描述
& 按位“与”运算符:参与运算的两个值,如果两个相应位都为 1,则结果为 1,否则为 0
| 按位“或”运算符:只要对应的两个二进制位有一个为 1 时,结果就为 1
^ 按位“异或”运算符:当两对应的二进制位相异时,结果为 1
~ 按位“取反”运算符:对数据的每个二进制位取反,即把 1 变为 0,把 0 变为 1
<< “左移动”运算符:运算数的各二进制位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃, 低位补 0
>> “右移动”运算符:运算数的各二进制位全部右移若干位,由“>>”右边的数指定移动的位数

上述位运算符的示例如下所示:
>>> a=55 #a=0011 0111
>>> b=11 #b=0000 1011
>>> print(a&b)
3
>>> print(a|b)
63
>>> print(a^b)
60
>>> print(~a)
-56
>>> print(a<<3)
440
>>> print(a>>3)
6

成员运算符

Python 的成员运算符

运算符 描述
in 当在指定的序列中找到值时返回 True,否则返回 False
not in 当在指定的序列中没有找到值时返回 True,否则返回 False

上述成员运算符的示例如下所示:
>>> a=1
>>> b=20
>>> l = [1, 2, 3, 4, 5]
>>> print(a in l)
True
>>> print(b not in l)
True

身份运算符

Python的身份运算符

运算符 描述
is 判断两个标识符是否引用自同一个对象,若引用的是同一个对象则返回 True,否则返回 False
is not 判断两个标识符是不是引用自不同对象,若引用的不是同一个对象则返回 True,否则返回 False

上述身份运算符的示例如下所示:
>>> a=123
>>> b=123
>>> c=456
>>> print(a is b)
True
>>> print(a is not c)
True

运算符优先级

Python 运算符优先级

运算符 描述
**
~ 按位“取反”
*、/、%、// 乘、除、取模、取整除
+、- 加、减
>>、<< 右移、左移
& 按位“与”
^、| 按位“异或”、按位“或”
<=、<、>、>= 比较运算符
==、!= 等于、不等于
=、%=、/=、//=、-=、+=、=、*= 赋值运算符
is、is not 身份运算符
in、not in 成员运算符
and or not 逻辑运算符

流程控制

Python 提供了现代编程语言都支持的两种基本流程控制结构,分支结构和循环结构:

  • 分支结构用于实现根据条件来选择性地执行某段代码;
  • 循环结构用于实现根据循环条件重复执行某段代码;

    条件语句

    单if语句

    语法格式:
    if 条件表达式:
      代码块
    
    执行流程:

Python入门以及在自动化中的使用 - 图3

代码示例:

age = 18
if age >= 18:
    print("可以进入网吧嗨皮了")

if else 语句

语法格式:

if 条件表达式:
    代码块
else:
    代码块

执行流程:

image.png

代码示例:

age = 18
if age > 18:
    print("可以去网吧嗨皮了")
else:
    print("未成年,请不要进入网吧")

if elif else 语句

语法格式:

if 条件表达式1:
    代码块1
elif 条件表达式2:
    代码块2
elif ...:
    .....
else:
    代码块3

执行流程:
image.png

代码示例:

day_num = int(input("请输入一个整型数字:"))
if num == 6:
    print("周六要加班")
elif num == 7:
    print("周天可以休息了")
else:
    print("挤公交,上班呀")

pass关键字的作用

pass 不做任何事情,一般用做占位语句。
代码示例:

age = 18
if age > 18:
    pass

本代码中使用了pass进行占位操作,实际开发中,如果我们暂时没有想到逻辑,可以使用pass进行占位。

循环语句

while循环

语法格式:

计数器变量
while 循环条件:
    循环体代码
    处理计数器

执行流程:
image.png

代码示例:

i = 0 # 程序中计数器从0开始
while i < 10:
    print("我是循环体")
    i += 1

range函数

range() 函数可创建一个整数列表,一般用在 for 循环中。
语法格式:

range(start, stop, step)

参数说明:

  • start: 计数从 start 开始。默认是从 0 开始。
  • stop: 计数到 stop 结束,但不包括 stop。
  • step:步长,默认为1。
  • 记住一句话:顾头不顾尾。

    for循环

    语法格式:
    for variable in sequence:
      语句块
    
    流程图:

image.png

示例代码:

for i in range(10):
    print(i)

循环嵌套

循环嵌套是指:在一个循环体里面嵌入另一循环。
实例1:通过while循环打印99乘法表

j = 1
while j <= 9:
    i = 1
    while i <= j:
        print('%d*%d=%d' % (i, j, i*j), end='\t')
        i += 1
    print()
    j += 1

实例2:通过for循环打印99乘法表

for j in range(1, 10):
    for i in range(1, j+1):
        print('%d*%d=%d' % (i, j, i*j), end='\t')
        i += 1
    print()
    j += 1

输出结果:

1*1=1    
1*2=2    2*2=4    
1*3=3    2*3=6    3*3=9    
1*4=4    2*4=8    3*4=12    4*4=16    
1*5=5    2*5=10    3*5=15    4*5=20    5*5=25    
1*6=6    2*6=12    3*6=18    4*6=24    5*6=30    6*6=36    
1*7=7    2*7=14    3*7=21    4*7=28    5*7=35    6*7=42    7*7=49    
1*8=8    2*8=16    3*8=24    4*8=32    5*8=40    6*8=48    7*8=56    8*8=64    
1*9=9    2*9=18    3*9=27    4*9=36    5*9=45    6*9=54    7*9=63    8*9=72    9*9=81

break关键字

Python中break关键字用来终止循环语句,即循环条件没有False的情况下,停止循环。
示例代码:

for i in range(10):
    if i == 5:
        break
    print("Bye")

注意:一旦使用了break,同等缩进的情况下,不能再有其他语句块。

continue关键字

Python中continue关键字跳出本次循环,进入下一次循环。
示例代码:

for i in range(10):
    if i == 5:
        continue
    print(i)

运行之后我们发现,没有数字5。即循环到5之后,终止本次循环进入下一次循环。

Python在自动化中的应用

概述

Python在自动化测试中的应用是比较多的,比如用Requests&Pytest可以做一个简单的接口测试框架,用Selenium可以做WEB的UI自动化测试,用Appium可以做APP的UI自动化测试等等。

在测试部门的应用

目前Python在非功能测试中使用的并不多,因为专项测试脚本基本都是用JS写的,只有Venus项目中的SMT(冒烟测试)是用Python&RobotFramework搭建的。
当前部门Leader也十分重视自动化,有专项小组来推进自动化在整个部门的使用。
image.png

STC_AutoTesting

该项目可能是未来部门主推的一个自动化测试工具,主要由Pytest&Allure&Zal库为基础来构建。

  • Pytest是一个非常成熟的全功能的Python测试框架
  • Allure测试报告直观、简洁、数据清晰越好,使用装饰器与pytest搭配使用
  • Zal库是与车机底层交互的工具库

    目录结构

    主代码

    | conftest.py | pytest通用插件 | | —- | —- | | pytest.ini | pytest运行时配置文件 | | pytest_helper.py | pytest运行时主控代码 | | pytest_cloudsparrow.py | 通过云雀执行pytest测试的主代码,会调用pytest_helper.py | | pytest_cloudsparrow.xml | 通过云雀执行pytest测试时,云雀生成的配置文件
    与pytest_cloudsparrow.py配合使用 | | pytest_suites_generator.py | 生成pytest测试用例集 | | results/ | 测试结果文件夹 | | pytestlib/ | 测试库 | | suites/ | 测试用例集 | | | |

测试库

pytestlib/ 测试库
├── asserts.py
├── fixtures pytest用到的各个纹理文件,可以在测试代码中直接使用
│ ├── init.py
│ ├── avn.py
│ ├── can.py
│ ├── common.py
│ └── ui.py
├── locators 车机控件定位文件
└── naming.py 测试项目、本地文件、carsim等命名映射

测试集

suites/ 测试用例集
├── conftest.py 用例集通用插件
├── suites.csv 用例集
└── AS22L 适用于AS22L的用例集
├──系统设置 一级模块
│ ├── 智能设置 二级模块
│ │ └── …… 三级模块
│ │ └── test系统设置智能设置.py 测试用例
│ │ └── conftest.py

具体使用

由于本人目前还没参与到该项目中,具体使用就附上一个框架开发同学的文档,后期应该也有详细的用例文档给大家的。
https://yuque.antfin.com/office/lark/0/2021/docx/14256366/1626420158912-b5b77f80-b535-4a37-93c8-26b9fc048285.docx?from=https://yuque.antfin.com/uwk7mr/lxax5x/hkantq

测试报告展示

云雀测试报告:
Python入门以及在自动化中的使用 - 图9
http://test.yunos-inc.com/openservice?executionId=956047&product=Car&type=pytest&tab=1&device=AS22L&hostname=guoxiangqiang.gxq&version=2.3.1-R-20210705.0122&producttag=YunOS&taskexecutionid=1876064
详细报告:http://oss-cn-hangzhou-zmf.aliyuncs.com/styunos/public/pytest/results/1876064/allure_report_dest/index.html#
Log: https://oss-cn-hangzhou-zmf.aliyuncs.com/styunos/public/pytest/results/1876381/Test_System_Settings_Data_flow.test_systemsetting_dataflow_video_ON1/pytest_logcat_20210715_155526.log
Python入门以及在自动化中的使用 - 图10
Python入门以及在自动化中的使用 - 图11