Python基本功

Python的标准数据类型有

  • Numbers(数字)

  • String(字符串)

  • List(列表)

  • Tuple(元组)

  • Dictionary(字典)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #定义数字变量
    total_num = 100
    #定义字符串变量
    welcome_words = "欢迎来到蔡超的测试开发课"
    #定义列表。列表元素可修改,也可以添加删除
    student_list = ["Kevin", "Emily", "Ray"]
    #定义元组(元组与列表类似,区别在于元组的元素不能修改)
    unique_student = ("Kevin", "Emily", "Ray")
    #定义字典,字典一般是key-value结构
    course_rank = {"math": "Kevin", "logic": "Emily", "English": "Ray"}

    List 常用操作

  • 计算列表元素个数

    • 语法:len(list)

    • 举例:

      1
      2
      3
      4
      5
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> len(list)
      5
  • 获取列表的第N个元素,数组下标从0开始

    • 语法:list[N]

    • 举例:

      1
      2
      3
      4
      5
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list[2]
      3
  • 往List的末尾添加一个元素

    • 语法:list.append(x)

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.append(8)
      >>> list
      [2, 5, 3, 7, 1, 8]
  • 扩展List,常常用来把一个可迭代数据的每一个元素append到List里, 它相当于a[len(a):] = iterable

    • 语法:list.extend(x)

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.extend([6, 2, 4])
      >>> list
      [2, 5, 3, 7, 1, 6, 2, 4]
  • 插入列表, 在第i个位置插入x元素

    • 语法:list.insert(i, x)

    • 举例

      1
      2
      3
      4
      5
      6
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.insert(0, 8)
      >>> list
      [8, 2, 5, 3, 7, 1]
  • 删除元素,删除列表里第一个元素,它的值等于x

    • 语法:list.remove(x)

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.remove(5)
      >>> list
      [2, 3, 7, 1]
  • 删除指定位置的元素,如果没有指定i,就删除最后一个元素并返回剩余的list

    • 语法:list1.pop(i)

    • 举例:

      1
      2
      3
      4
      5
      6
      7
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.pop(0)
      2
      >>> list
      [5, 3, 7, 1]
  • 清空列表

    • 语法:list.clear()

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> list = [2, 5, 3, 7, 1]
      >>> list
      [2, 5, 3, 7, 1]
      >>> list.clear()
      >>> list
      []
  • 返回list中x出现的次数

    • 语法:list.count(x)

    • 举例:

      1
      2
      3
      4
      5
      >>> list = [2, 5, 3, 7, 2, 1]
      >>> list.count(2)
      2
      >>> list.count(7)
      1
  • 给列表排序, 把list安装key的值来排序, 当reverse等于true时为倒序

    • 语法:list.sort(key=None, reverse=False)

    • 举例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      >>> list = [2, 5, 3, 7, 2, 1]
      >>> list
      [2, 5, 3, 7, 2, 1]
      >>> list.sort()
      >>> list
      [1, 2, 2, 3, 5, 7]
      >>> list.sort(reverse=True)
      >>> list
      [7, 5, 3, 2, 2, 1]

      注意:true和false的首字母要大写

  • 翻转列表

    • 语法:list.reverse()

    • 举例:

      1
      2
      3
      4
      >>> list = [2, 5, 3, 7, 2, 1]
      >>> list.reverse()
      >>> list
      [1, 2, 7, 3, 5, 2]

Dictionary 常用操作

  • 定义字典:key-value

    • 语法:{}

    • 举例:

      1
      2
      3
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
  • 获取key的值,返回指定键的值,如果字典里没这个可以则返回default的值

    • 语法:dict.get()

    • 举例:

      1
      2
      3
      4
      5
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> dict.get("Math")
      'May'
  • 获取不存在的值Chemistry, 则返回Ray

    • 语法:dict.get()

    • 举例:

      1
      2
      3
      4
      5
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> dict.get("Chemistry", "Ray")
      'Ray'
  • 获取字典里的所有key

    • 语法:dict.keys()

    • 举例:

      1
      2
      3
      4
      5
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> dict.keys()
      dict_keys(['Math', 'Chinese', 'English'])
  • 获取字典所有的values

    • 语法:dict.values()

    • 举例:

      1
      2
      3
      4
      5
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> dict.values()
      dict_values(['May', 'Hong', 'Anna'])
  • 获取字典的key和value

    • 语法:for k, v in dict.items():...

    • 举例:

      1
      2
      3
      dic = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      for k, v in dic.items():
      print('{key} -- {value}'.format(key=k, value=v))

      执行结果:

      image-20201207191634214

  • 改变字典的值

    • 语法:dict[key] = value

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> dict["Chinese"]="wang"
      >>> dict
      {'Math': 'May', 'Chinese': 'wang', 'English': 'Anna'}
  • 删除字典的某个值

    • 语法:del dict[key]

    • 举例:

      1
      2
      3
      4
      5
      6
      >>> dict = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dict
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> del dict["English"]
      >>> dict
      {'Math': 'May', 'Chinese': 'wang'}
  • 删除字典

    • 语法:del dict

    • 举例:

      1
      2
      3
      4
      5
      6
      7
      8
      >>> dic = {"Math":"May", "Chinese":"Hong", "English":"Anna"}
      >>> dic
      {'Math': 'May', 'Chinese': 'Hong', 'English': 'Anna'}
      >>> del dic
      >>> dic
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      NameError: name 'dic' is not defined

Python 控制流

while 循环

img

while 循环的作用在于,当某个条件成立时,一直执行循环语句, 直至循环条件不成立为止。

1
2
3
4
5
#while循环
while 判断条件(condition):
执行语句(statements)
……

当你无法确定循环的次数时,通常使用 while 循环指定一个循环执行条件。

for 循环

img

需要对列表、字典等进行遍历操作时,我们通常会用到 for 循环。

1
2
3
4
5
6
#for循环
for iterating_var in sequence:
执行语句(statements)
……


当对列表、字典进行遍历时,或者当你能确定循环的次数时,通常使用 for 循环。

if 语句

img

if…else…语句用处非常广泛,当业务逻辑需要判断某个条件是否成立时,就可以用 if…else…语句。

1
2
3
4
5
6
7
#分支语句
if 条件:
执行条件语句A(statements)
else
  执行条件语句B(statements)


控制流应用案例

结合以上的控制流的学习,实现一个应用案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 定义一个list类型的数据变量list,存放老师姓名
teacher = ["May", "Anna"]
# 定义一个dict类型的变量,存放老师代课的课程
course = {"Math": "May", "Chinese": "Hong", "English": "Anna"}
# main函数调用
if __name__ == '__main__':
# 定义一个字典good_course存放课程教的最好的老师
good_source = {}
# 循环获取course里的所有key和value,如果value在我的学生列表teacher里,则把老师名字作为key,课程作为value保存在新建立的字典good_source里。
for k, v in course.items():
if v in teacher:
good_source[v] = k
# 获取教学好的老师的人数
p_len = len(good_source)
# 循环字典里的每个key和value,把老师擅长教的科目打印出来
while p_len > 0:
for p in good_source.keys():
print('{teacher} is good at {course}'.format(teacher=p, course=good_source[p]))
p_len -= 1

执行结果:

image-20201207193713463

函数、模块、包

通常我们的代码为了方便调用,都会以函数、模块、包等形式存在。

函数

函数就是能实现一定功能的代码语句的集合。在 Python 中定义函数很简单:

1
2
3
def 函数名(参数):
函数体

Python 函数定义同样支持无形参、有形参、可变参数等;而函数可以有返回值,也可以没有返回值。

  • 无形参—不需要参数输入

    1
    2
    3
    4
    5
    6
    7
    # 无形参,无返回值
    def hello():
    print("Hello, Python")


    if __name__ == '__main__':
    hello()
  • 有形参—函数接受用户参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    # 有一个形参,有返回值
    def is_true(x):
    return x > 0


    # 有两个形参,有返回值
    def min_number(x, y):
    # 如果x大于y,则将x与y交换后,返回x,否则直接返回x
    if x >= y:
    x, y = y, x
    return x


    # 有可变个形参,有返回值
    def sum_number(*args):
    # 求和
    total = 0
    for k in args:
    total += k
    return total


    # 可变形参,接收key-value的形式,无返回值
    def count_teacher(**kwargs):
    for k, v in kwargs.items():
    print('{0} - {1}'.format(k, v))


    if __name__ == '__main__':
    print(is_true(5))
    print(min_number(6, 8))
    print(sum_number(1, 2, 3))
    count_teacher(Math='May', Chinese='Hong')

模块

模块是为了编写可维护的代码,而把函数分组放到不同文件里的行为。在 Python 中,一个 .py文件 就是一个模块,一个模块可以包括一个或多个功能,模块又可以被一个或多个其他模块引用。

使用模块的好处很多, 我讲典型的两个:

  • 既提高了编程的效率,也增强了代码的可维护性。

把模块导入当前模块,当前模块即可拥有模块已经实现的功能。如果模块的功能本身需要更改,我们只需要更改模块定义的地方即可,其他地方都无须更改。

  • 不同模块的函数名和变量名可以重名。

有了模块,避免了函数名和变量名之间的冲突,例如如下的文件结构:

1
2
3
4
python-project
|--module1.py
|--module2.py

假设我在 module1.py 里和 module2.py 里,同时定义一个名字为eat() 的函数。这两个不同模块的函数虽然都叫 eat,但其行为可以不相同,也不会相互影响。

如果模块名也相同怎么办呢?为了解决这个问题,Python 又定义了包(Package)。包就是一个目录文件,它必须包含一个名为 __init__.py 的文件。

如下就是一个包结构,在一个包里,不同层级目录下可以包含名字相同的模块。

1
2
3
4
5
6
7
8
python-project
|-- web
|-- module.py
|-- __init__.py
|-- API
|-- module.py
|-- __init__.py
|-- __init__.py

在 web 层级和 API 层级它们都包含着名字相同的模块 module.py,以下列出不同包下的模块引用方式:

1
2
3
4
# 引入web目录下的包, 假设此目录下module.py里有类变量Module
from web.module import Module
# 引入API目录下的包,假设此目录下module.py里有类变量Module
from API.module import Module

可以看出来,函数、模块、包的作用是把代码模块化,方便我们调用和写出更高效的编写代码。

模块的导入

一个模块是如何被其他模块调用的呢?

直接导入模块

1
2
#假设module1.py文件里有个eat方法
import module1

采用这种方式导入后,就可以直接使用

1
module1.eat()

如果 module1 里含有其他函数,在 module1 被导入后,均可以通过 module1.xxx() 的方式来使用。

采用 from…import 方式导入

有时候我们并不想把一个模块的所有功能都导入进来,假设我只想使用 eat 这一个方法,那么我可以使用 from…import 的方式:

1
from module1 import eat

采用这种方式导入后,如果我要使用 eat 函数,我可以直接在代码里以如下方式使用:

1
eat()

可以注意到,这种情况我就不必要写模块名字了。

但假设这个模块里还有个 xxx 函数,我在没有导入的情况下,是无法直接通过 module1.xxx() 或者 xxx() 这样的方式使用的。

采用 from…import* 方式导入

如果你想一次性地导入一个模块下的所有函数, 你可以使用如下方式:

1
from module1 import *

采用这种方式导入后,你可以直接使用这个模块下的所有函数。

动态导入

上面介绍的三种导入方式都属于静态导入,这个很好理解。

但在实际应用中,也会有在程序运行时才知道要具体导入哪个模块的情况(例如,测试框架自动查找测试用例并导入测试用例所属的模块),这时就需要动态导入。

动态导入常常用 importlib 来完成,常用的动态导入有以下两种方式:

  • 从模块直接导入

    1
    2
    3
    import importlib 
    #导入a.b模块
    mod = importlib.import_module( "a.b"
  • 根据模块名,文件名导入

    1
    2
    3
    4
    import importlib.util
    spec = importlib.util.spec_from_file_location("a.b", "/path/to/file.py")
    md = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(md)

这个方式比较常用。下面我来举个具体的例子, 假设现在我们的项目目录情况如下:

1
2
3
4
5
python-project
|-- tests
|-- a.py
|-- __init__.py
|-- b.py

在模块 a.py 里,我定义了一个函数:

1
2
def hello():
print("I'am module a!")

现在,我想在模块 b 中使用 hello() 这个函数, 要怎么操作呢?在b.py写入如下操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import glob
import importlib.util
import os


def find_modules_from_folder(folder):
"""
获取当前目录下所有的模块, *.py
:param folder: 文件路径
:return: 返回模块名与模块绝对路径
"""
absolute_f = os.path.abspath(folder)
# 匹配*.py模块
md = glob.glob(os.path.join(absolute_f, "*.py"))
return [(os.path.basename(f)[:-3], f) for f in md if os.path.isfile(f) and not f.endswith('__init__.py')]


def import_modules_dynamically(model, file_path):
# 进行动态加载
spec = importlib.util.spec_from_file_location(model, file_path)
md = importlib.util.module_from_spec(spec)
spec.loader.exec_module(md)
return md


if __name__ == "__main__":
module = find_modules_from_folder('.')
for m in module:
mod = import_modules_dynamically(m[0], m[1])
mod.hello()

这个代码有点复杂,我先给定一个文件夹,然后通过函数 find_modules_from_folder 来得到这个文件夹下的模块,及其对应的文件路径,然后我再通过 spec_from_file_location 来动态加载。