python自动化测试 第 4 章.函数与代码复用

函数与代码复用

从上往下执行,根据逻辑的过程一条一条去运行,面向过程编程。一步一步的执行。

函数式编程(很难,编程范式,) 面向函数

面向过程, 面向对象,函数编程
看下面一段伪代码:

    if cpu使用率 >80%:
        连接邮箱
        发送邮件
        关闭邮箱
    if 内存使用率 >80%:
        连接邮箱
        发送邮件
        关闭邮箱
    if 硬盘使用率 >80%:
        连接邮箱
        发送邮件
        关闭邮箱
  • 面向过程编程
    • 优点:逻辑清晰,简单易懂
    • 缺点:代码冗余问题,很多重复的代码

1. 函数的概念

把一段具有特定功能的,语句组,用函数名来表示,通过函数名来调用完成功能。

函数也可以看做是一段具有名字的程序,在需要的地方调用执行,不需要在每个执行地方重复编写这些代码。

函数式一种功能的抽象。

  • 优点:解决了代码冗余的问题
  • 缺点;执行流程不直观(相对面向过程来说会难理解)

2. python中函数的定义

语法:

def 函数名(参数1,参数2,...):
  函数体(多行完成特定功能的代码)
  return 返回值

原则:

  • 函数体最好不要超过一页(太长了不好)

  • 功能单一(如果功能太多,有多处要调用时其中某个功能时,调用不方便)

3. 函数的调用过程

    1. 调用程序在调用处暂停执行后面的程序,先跳转到函数体里面执行函数代码
    1. 在调用时将实参赋值给函数的形参
    1. 执行函数体语句
    1. 函数调用结束返回结果,程序回到调用处向前继续执行

4. 函数的参数

定义函数时 ()里面的参数叫形参(形式参数),就是一个变量名,供函数体里的代码调用

调用函数时,传入()里的参数叫实参(实际参数),它就是实际数据,会传递给形参

4.1 形参

4.1.1 必须参数

必须传递的实际参数

直接定义在函数名后的()里的参数就是必须参数

案例:

定义一个函数,接收两个数,然后打印他们的和

def func(a, b):
    print(a+b)


func(1, 2)

4.1.2 默认参数

在函数名后() 中,以参数名=默认值的形式定义的形参,就叫做默认参数。

案例:

定义一个函数,它接受两个参数content和times,

  • content 是函数要打印的内容
  • times是函数打印的次数,如果不传递默认打印一次

注意:默认形参必须定义在必须形参的后面

def func(content, times=1):
    for _ in range(times):
        print(content)


func('Hello, World', times=10)  # 调用时,可以不传times,就默认times=1

for循环,当循环变量在循环体中不使用时,常用下划线表示,如上述例子

4.1.3 不定参数

定义函数的时候,不确定调用的时候回传递多少个实参

位置不定参

在函数名的()中,在形参的前面加上一个*号可以定义位置不定参,通常这个形参叫args

args会接收函数调用时,以位置方式传递过来的超过了形参数量的多余的实参,作为元组;
比如:
下述例子中,func定义时定义了1个必须参数和位置不定参,调用时,如果传递了三个参数,即除了前面1个必须参数,剩下的参数会组成一个元组

def func(a, *args):
    print(a, args, type(args))

func(1) # 输出1 () <class 'tuple'>
func(1,2) # 输出1 (2,) <class 'tuple'>
func(1,2,3) # 输出1 (2,3) <class 'tuple'>
案例:

定义一个函数,接受2个以上的数,打印它们的和。

def my_sum(x, y, *args):
    res = x + y
    for i in args:
        res = res + i
    print(res)


my_sum(1, 2, 3, 4)
关键字不定参

在函数名后的()中,在形参的前面加上**号,可以定义关键字不定参,通常参数名叫 kwargs

它用来接受函数调用时,以关键字的方式传递过来的多余的实参,并组成一个字典。

def func(a, **kwargs):
    print(a, kwargs, type(kwargs))

func(1, b=2) # 1 {'b': 2} <class 'dict'>
func(a=1, b=2, c=3) # 1 {'b': 2, 'c': 3} <class 'dict'>

形参定义的顺序(语法)

必须按照顺序:必须参数,默认参数,位置不定参,关键字不定参

4.2 实参

4.2.1 位置传递

调用函数时,传递实参默认会按照形参的位置一一对应

案例

定义一个函数,实现打印一个数的n次幂

def func(x, n):
    res = x**n
    print(res)


func(2, 3)
func(3, 2)

4.2.2 关键字传递

传递实参时,以形参名=实参的形式传递参数,关键字参实参

当一个函数的参数很多的时候,记不住位置的时候,手动指定

注意:关键字参数要放在位置参数的后面

def func(x, n):
    res = x**n
    print(res)


func(2, n=3)  # 等价于func(x=2, n=3) 或func(n=3,x=2) 
func( n=3,2)  # 会报错,3和2都传给n,x没有传递到参数,关键字参数要放在位置参数的后面
func( 3,x=2)  # 会报错,3和2都传给x了

5. 参数解包

*,**在传递实参的时候的用法也叫参数解包
*可以在传递实参的时候解包可迭代对象 =》 把迭代对象里的每一个元素按照位置参数依次传入函数

*解包

def add(x,y,*args):
    sum = x + y
    for i in args:
         sum += i
    print(sum)


ls = [i for i in range(10000)]
add(*ls)  # 相当于add (ls[0],ls[1],....ls[9999])
add(*range(10000)) # 也等价于这么写,因为range(10000)是一个可迭代对象,可以对其进行解包

列表生成式

ls = [i for i in range(10000)] # 创建0到9999,步长为1的列表
print(ls)

** 解包

在传递实参的时候,可以通过**字典对象进行解包

以key=value的关键字的形式传递实参

def connect(host,db,user,pwd,charset):
    """
    假装是一个连接数据库的函数
    """
    print('你要连接的数据库地址是{},数据库名是:{},用户名:{},密码是:{},字符集是{}'.format(host, db, user, pwd, charset))

db_config = {
'host':'127.0.0.1',
'db':'pye34',
'user' : 'root',
'pwd':'123456',
'charset':'utf-8'
} # 先定义一个字典
connect(**db_config)  # 调用函数时用解包方法传参

connect(host=db_config['host'], db=db_config['db'], user=db_config['user'], pwd=db_config['pwd'], charset=db_config['charset']) # 等价于上面的方式,不如上面方式好

6 函数返回值

return 关键字来返回结果,并退出函数。

在函数里一旦执行return 函数就退出了

return 可以返回 0 个,1个,多个函数运行结束后的结果,返回多个值的时候,返回元组(安全,取值高效)

函数可以没有返回值,也就是可以没有return 语句, 这是函数返回None

def add(x, y, *args):
    sum = x + y
    for i in args:
        sum = sum + i
    return sum

res=add(1, 2,3)
print(res)

案例:返回多个值
定义一个函数接受被除数x和除数y,返回他们的商和余数

def my_mod(x, y):
    s_g = None  
    y_s = None
    if x < y:
        s_g = 0
        y_s = x
    else:
        s_g = 0
        while x >= y:
            x = x-y
            s_g += 1
        y_s = x
    return s_g, y_s

res = my_mod(10,3)
print(res)

如果想返回列表,或者字典,就要在return语句定义好对应类型

def my_mod(x, y):
    s_g = None
    y_s = None
    if x < y:
        s_g = 0
        y_s = x
    else:
        s_g = 0
        while x >= y:
            x = x-y
            s_g += 1
        y_s = x
    return [s_g, y_s]  # 返回列表
    return {'商': s_g, '余数': y_s}  # 返回字典

res = my_mod(10,3)
print(res)  # [10, 3],{'商': 3, '余数': 1}

**执行return语句后,函数会终止执行

def is_odd(num):
    if num % 2 == 0:
        return False
    return True # 此处可以省略else语句,因为if的条件成立后,就return False了,程序就已经结束了,如果if条件不成立就跳过return False,继续向下执行,此时就会执行return True了;不是所有的else都能省略,此处是因为有return,比如下面的程序就不能省略else


print(is_odd(1))


score = int(input('输入一个整数'))
if score > 0:
    print('正数')
else:                        
  print('非正数')  # 不能省略else,如果省略,输入正数时,两个print语句都会执行,也就是说, print('非正数')这个语句是必然执行的

7. lambda函数

匿名函数,用来定义简单的,能够在一行内表示的函数。
语法:

lambda arg1,arg2,...: expression

看下面列子,怎么把成绩从小到大排列

ls = [('语文', 100),('数学', 99),('英语', 88)]
# 试试用列表的排序方法
ls.sort()
print(ls) # 输出[('数学', 99), ('英语', 88), ('语文', 100)]

.sort()这个方法是默认对第一个元素进行排序,也就是(语文,数学,英语),按照第一个字符编码顺序(语,数,英)
help(ls.sort)
查看对应的用法
sort(*, key=None, reverse=False) method of builtins.list instance
Stable sort IN PLACE.
key=None,key是一个函数,是排序的依据,所以要写一个函数来获取列表中各元素的分数

ls = [('语文', 100),('数学', 99),('英语', 88)]
ls.sort()

def sort_by(item): # item是一个二元元组
    return item[1]  # 获取分数

ls.sort(key=sort_by)
print(ls)

下面程序等价于上面的程序,使用lambda函数的写法更加好

ls = [('语文', 100),('数学', 99),('英语', 88)]
ls.sort()

ls.sort(key=lambda item: item[1]) #利用lambda函数的写法
print(ls)

ls.sort(key=lambda item: item[1], reverse=True) #分数从大到小排列

def fun(x, y):
    return x + y

# 等价于下面这个
func = lambda x, y: x+y

lambda 函数一般不会直接定义,通常是作为参数传递给其他函数作为参数使用。

8. 变量作用域

变量能够被访问的范围,就要做作用域。

  • 全局作用域 - 全局变量
  • 局部作用域 - 局部变量

全局变量能够被函数里访问

s = 1
def fun():
    print(s) #在函数里面调用全局变量s

fun()

在函数的外面 不能访问函数里面的变量

 def fun():
     b = 2  # 局部变量
     print(b)

print(b) # 报错

找变量只能从里往外找

b=1
def fun():
    b = 2  # 局部变量
    print(b)

fun()  # 打印出局部变量2

全局变量名和局部变量名重名不起冲突的,一般上不要取重复名字的变量

在函数里面不能直接修改不可变的全局变量,如果是可变的数据类型(如:列表),可以在函数中直接修改

b=1
def fun():
    b = b + 2  # 会出现报错,因为函数中没定义变量b,虽然全局变量定义了b,但是函数无法直接修不可变的全局变量
    print(b)

fun()  

用global改变全局变量(不可变类型)

a = 1

def fun():
    global a    # 申明 a是全局变量
    a += 1

fun()

9. python的内置(内建)函数

import builtins
print(dir(builtins))

大写字母开头的是异常类型,小写开头的是python内置函数
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

常用的内置函数

9.1获取最大/小值,max与min

min(1,2,3)
min([1,2,3])
min('abcdefg')
max('abcdefg')

9.2print函数

print(value,..,sep=' ', end='\n')

  • value 会打印 value 的字符串形式
  • sep 分隔符,当有多个 value 时默认用空格作为分割
  • end 每次打印在最后默认添加回车换行符
    打印传入对象的字符串形式
print(1,2,3,sep=',')
1,2,3

print(1,end='')
print(2)

9.3 input

接收用户的输入数据,以字符串的形式返回。

可以接收字符串参数最为提示信息输出

9.4 type

type(object)
返回 object 的类型

9.5 dir

dir([object])
返回传入对象的所有属性和方法名的列表

print(dir(1))
['abs', 'add', 'and', 'bool', 'ceil', 'class', 'delattr', 'dir', 'divmod', 'doc', 'eq', 'float', 'floor', 'floordiv', 'format', 'ge', 'getattribute', 'getnewargs', 'gt', 'hash', 'index', 'init', 'init_subclass', 'int', 'invert', 'le', 'lshift', 'lt', 'mod', 'mul', 'ne', 'neg', 'new', 'or', 'pos', 'pow', 'radd', 'rand', 'rdivmod', 'reduce', 'reduce_ex', 'repr', 'rfloordiv', 'rlshift', 'rmod', 'rmul', 'ror', 'round', 'rpow', 'rrshift', 'rshift', 'rsub', 'rtruediv', 'rxor', 'setattr', 'sizeof', 'str', 'sub', 'subclasshook', 'truediv', 'trunc', 'xor', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

9.6help

help(builtins.object)
返回内建对象的帮助信息

help(help)

9.7len

len(obj)
返回容器的元素个数

len([1,2,3])

9.8hash

hash(obj)
返回对象的 hash 值

hash('a')
3636161774609400683

9.9iter

iter(iterable)
根据传入的可迭代对象返回一个迭代器

iter('abcd')
<str_iterator at 0x7f98b7dd2eb0>

9.10id

id(obj)
返回传入对象的身份 id(虚拟内存地址的整数形式)

id(1)
4344134656

9.11range

range(stop) -> range object
range(start, stop[,step])
返回一个 range object 对象,产生整数序列

range(10)

更多的方法查看官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容