一、背景

在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while True
    if cpu利用率 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
 
    if 硬盘使用空间 > 90%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接
 
    if 内存占用 > 80%:
        #发送邮件提醒
        连接邮箱服务器
        发送邮件
        关闭连接

上面代码可以看出,整个发邮件的代码都是重复的,可以优化成以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def 发送邮件(内容)
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
while True
 
    if cpu利用率 > 90%:
        发送邮件('CPU报警')
 
    if 硬盘使用空间 > 90%:
        发送邮件('硬盘报警')
 
    if 内存占用 > 80%:

优化后的代码无论是从可读性还是重用性上都要比之前的代码要好,这就是函数式编程和面相过程变成的区别:

  • 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可

  • 面相对象:对函数进行分类和封装,让开发“更快更好更强”

函数式编程最重要的是增强代码的重用性和可读性。

二、函数的定义和使用

1
2
3
4
5
def 函数名(参数):
 
    函数体
 
    返回值

函数的定义主要有如下五点:

  1. def:函数的关键字,python解释器读到这里,知道是要定义函数了

  2. 函数名:函数的名称,日后通过函数名来调用函数

  3. 函数体:函数中进行一系列的逻辑计算,

  4. 参数:为函数体提供数据

  5. 返回值:当函数执行完毕后,可以给调用者返回数据。让调用者知道,函数是否执行成功。

1、返回值

返回值用来告知调用者函数是否执行成功

1
2
3
4
5
6
7
8
9
10
11
def f1():
    print(123)
    # 在函数中,一旦执行return,函数执行过程立即终止
    return "111"
    print(456)
 
= f1()
print(r)
执行结果:
123
111

从上面的结果可以看出,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。

2、参数

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
def CPU报警邮件()
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
def 硬盘报警邮件()
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
def 内存报警邮件()
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
while True
 
    if cpu利用率 > 90%:
        CPU报警邮件()
 
    if 硬盘使用空间 > 90%:
        硬盘报警邮件()
 
    if 内存占用 > 80%:
        内存报警邮件()

以上例子可以看出,如果没有参数,无法自定义邮件内容,不灵活。带参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def 发送邮件(邮件内容)
 
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
 
 
while True
 
    if cpu利用率 > 90%:
        发送邮件("CPU报警了。")
 
    if 硬盘使用空间 > 90%:
        发送邮件("硬盘报警了。")
 
    if 内存占用 > 80%:
        发送邮件("内存报警了。")
这样可以清晰看出来邮件报警,哪里出了问题。
a.普通参数(严格按照顺序,将实际参数赋值给形式参数)
1
2
3
4
5
6
def f1(name):                 #name叫做函数的形式参数,简称形参
    print(name)
 
f1('yangyang')                #yangyang叫做函数f1的实际参数,简称实参
执行结果:
yangyang
b.指定参数
1
2
3
def f1(name,age,sex):
      print(name,age,sex)
f1(age=22,name='yangrz',sex='man')

c.默认参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def send(yy, content, xx="OK"):
    #定义函数时,xx="OK"  这种写法为默认参数,如果调用函数时不指定,则默认输出此值(OK)。
    #默认参数必须放置在参数列表的最后
    print(yy, content, xx)
    print("发送邮件成功:", xxoo, content)
    return True
 
while True:
    em = input("请输入邮箱地址:")
    result = send(em, "didi""ok")
    #em、didi、ok分别对应定义函数时,send()中的yy,content,xx。如果不写ok,name输出xx时,默认为OK。
    if result == True:
        print("发送成功")
    else:
        print("发送失败")

默认参数必须放置在参数列表的最后,如果调用函数时不指定,则默认输出定义函数时定义的值。

d.动态参数
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
35
36
37
38
*      默认将传入的参数,全部放置在元组中, f1(*[11,22,33,44])
def f1(*args):
    # args = (11,)
    args = ([11,22,"alex""hhhh"],"12")
    print(args, type(args))
f1()
执行结果:
([1122'alex''hhhh'], '12') <class 'tuple'>
由执行结果可以看出,*args 参数会把所有的值放置到元组中。
def f1(*args):
    print(args)
f1(11,22,33,44)
#执行结果:
(11223344)
#把传入的参数放置到元组中
li = [11,22,33,44,]
f1(*li)
#通过*列表名的方式将列表传入到函数中,把列表中的每一个值添加到元组中
执行结果:
(11223344)
f1(li)
#不加*,将整个列表作为一个元素添加到元组
执行结果:
([11223344],)
**     默认将传入的参数,全部放置在字典中   f1(**{"kl":"v1""k2":"v2"})
def f1(**args):
    print(args)
#执行方式一
f1(n1="biubiubiu", n2=18,"name"="yangrz")
执行结果:{'n1''biubiubiu',n2:18,"name":"yangrz"}
#执行方式二,定义字典,结果kk:{字典}
dic = {'k1'"v1""k2":"v2"}
f1(kk=dic)
执行结果:{'kk': {'k2''v2''k1''v1'}}
dic = {'k1'"v1""k2":"v2"}
#把字典的元素传入到函数中
f1(**dic)
执行结果:{'k2''v2''k1''v1'}
e.万能参数 (*args,**kwargs)
1
2
3
4
5
6
7
8
9
10
11
def f1(*args, **kwargs):
    #传入的是数字、字符串、列表就传入*args,如果是字典就传入**kwargs
    print(args)
    print(kwargs)
 
f1(11,22,33)
# 执行结果:
# (11, 22, 33)
# {}
f1(k1="v1")
执行结果:{'k1''v1'}
利用动态参数实现format功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# format的方法如下:
def format(*args, **kwargs):
#万能参数,故可以使用以下三种方式实现format功能
s1 = "My name is {0} age {1}".format("yangrz",18)
#*args接收字符串
print(s1)
# 执行结果:My name is yangrz age 18
s2 = "My name is {0} age {1}".format(*["yangrz",18])
#*args接收*列表的方式,把列表中的值传入
print(s2)
# 执行结果:My name is yangrz age 18
s3 = "My name is {name} age {age}".format(**{"name":"yangrz","age":19})
#**kwargs通过**字典的方式,将字典中的key-values传入
print(s3)
#执行结果:My name is yangrz age 19
函数中的异常处理(try语句)
1
2
3
4
5
6
7
8
9
10
11
def func():
    try:
       print(123)
    except:
       print("执行失败")
    else:
       print("执行成功")
func()
# 执行结果:
# 123
# 执行成功

该种异常处理语法的规则是:

·   执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。

·   如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。

·   如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。

·   如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。

·   如果没有发生异常,则执行else块代码。

三、函数内容补充

1
2
3
4
5
6
def f1(a1):
    a1.append(999)
li = [11,22,33]
f1(li)
print(li)
执行结果:[112233999]

说明:函数传入参数的时候,传入的是引用。列表li传入a1后,a1引用的内存中li开辟的列表空间,因此当a1.append(999)时,列表li的值也是会变的。

1
2
3
4
5
6
7
8
def f1(a1, a2):
    print(a1 + a2)
 
def f1(a1, a2):
    print(a1 * a2)
 
f1(8,8)
#执行结果:64

在python解释器中,上段代码的执行顺序:

1、定义函数f1,指向内存中的一块儿空间(print(a1 + a2))

2、定义函数f1,指向内存中的另一块儿空间(print(a1 * a2))

3、执行f1(8,8)

因为此时函数f1指向的是后来定义的(print(a1 * a2)) ,故结果为64.

函数的全局变量:

局部变量:自己创建自己用

全局变量:所有的作用域里都能读

对全局变量进行【重新赋值】,需要global

特殊的:列表字典,可修改,不可重新赋值

1
2
3
4
5
6
7
name = "yangrz"
def f1():
    age = 18
    name = "123"
    print(age,name)
f1()
#执行结果:18 123

如果函数中调用的变量在函数中存在、全局中也存在,优先使用自己定义的变量,如果自己没有定义这个变量,再去父类去找,父类没有,再向上一层一层去找。

1
2
3
4
def f1():
    age = 18
print(age)
#这样执行会报错

函数中的变量,外部无法使用。只能自己使用。

global可以在函数中对全局变量重新赋值:

1
2
3
4
5
6
7
age = 10
 
def f1():
    global age
    age = 18
f1()
print(age)

全局变量的命名规则:

全部都是大写,如:NAME = 'yangrz'  AGE = 19,这样在引用的时候,就知道它是全局变量。

四、内置函数

 

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
35
36
37
38
39
40
41
42
43
44
45
= abs(-1)
#abs()求绝对值
print(n)
# 执行结果  1
 
#0,None,"",[],(),{}   这些值的结果都是False
= all([1,2,3,None])
#all()里边是一个可迭代东西,只要里边有一个为False,结果就是False
print(n)
#执行结果:False
= any([1,0,(),None])
#与all相反,只要里边有一个为True,结果就为True
print(n)
#执行结果:True
 
ascii()
#自动执行对象的__repr__方法
# bin()
# oct()
# hex()
#以上三个函数,分别是输出一个10进制数字的2进制、8进制、16进制的表示
print(bin(10))
print(oct(10))
print(hex(10))
#执行结果:
        0b1010
        0o12
        0xa
#utf-8 一个汉字占3个字节
#gbk 一个汉字占2个字节
# bytes()
= "李杰" #一个字节8位,一个汉字三个字节
#01010101 10101010 10101011 01010101 10101010 10101011
#   23        23       23       23       23      23
#   2f        2f       2f       2f       2f      2f
#bytes()  把字符串转换成字节类型
#用法:bytes(要转换的字符串, 按照什么编码)
print(bytes(s,encoding="utf-8"))
#执行结果:b'\xe6\x9d\x8e\xe6\x9d\xb0'
print(bytes(s,encoding="gbk"))
#执行结果:b'\xc0\xee\xbd\xdc'
 
#str(字节,encoding="utf-8")   把字节转换成字符串
print(str(bytes(s,encoding="utf-8"),encoding="utf-8"))
#执行结果:李杰

 

python(四)函数的更多相关文章

  1. Python 全栈开发四 python基础 函数

    一.函数的基本语法和特性 函数的定义 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的.函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数 ...

  2. python学习笔记(四):函数

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...

  3. Python中函数传递参数有四种形式

    Python中函数传递参数有四种形式 fun1(a,b,c) fun2(a=1,b=2,c=3) fun3(*args) fun4(**kargs) 四种中最常见是前两种,基本上一般点的教程都会涉及, ...

  4. Python虚拟机函数机制之位置参数(四)

    位置参数的传递 前面我们已经分析了无参函数的调用过程,我们来看看Python是如何来实现带参函数的调用的.其实,基本的调用流程与无参函数一样,而不同的是,在调用带参函数时,Python虚拟机必须传递参 ...

  5. Python之函数与变量

    本节内容 函数介绍及其作用 函数的定义与调用 函数的参数说明 全局变量与局部变量 值传递和引用传递 一.函数的介绍及其作用 编程语言中的函数与数学中的函数是有区别的:数学中的函数有参数(输入),就会有 ...

  6. Python之函数进阶

    本节内容 上一篇中介绍了Python中函数的定义.函数的调用.函数的参数以及变量的作用域等内容,现在来说下函数的一些高级特性: 递归函数 嵌套函数与闭包 匿名函数 高阶函数 内置函数 总结 一.递归函 ...

  7. python 中函数的参数

    一.python中的函数参数形式 python中函数一般有四种表现形式: 1.def function(arg1, arg2, arg3...) 这种是python中最常见的一中函数参数定义形式,函数 ...

  8. python 中函数参数传递形式

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  9. 第三章:Python基础の函数和文件操作实战

    本課主題 Set 集合和操作实战 函数介紹和操作实战 参数的深入介绍和操作实战 format 函数操作实战 lambda 表达式介绍 文件操作函数介紹和操作实战 本周作业 Set 集合和操作实战 Se ...

随机推荐

  1. SpringMVC如何接收application/json内容编码类型的参数?

    在上代码之前,有必要先说说@ResquestBody注解的含义: 1.官方解释如下: Annotation indicating a method parameter should be bound ...

  2. IOS第16天(2,Quartz2D下载进度条)

    *************自定义下载的view的方法 #import "HMProgressView.h" @interface HMProgressView() @propert ...

  3. 【iCore3 双核心板】iCore3封装库及使用说明V1.0

    iCore3封装库及使用说明下载链接: http://pan.baidu.com/s/1pLq23Qb iCore3 购买链接: https://item.taobao.com/item.htm?id ...

  4. what's the difference between dim as and dim as new?

    what's the difference between dim as and dim as new? There is no difference with value types (Intege ...

  5. Python strip函数用法小结

    声明:s为字符串,rm为要删除的字符序列 s.strip(rm)        删除s字符串中开头.结尾处,位于 rm删除序列的字符 s.lstrip(rm)       删除s字符串中开头处,位于 ...

  6. CentOS - 开机自动发送IP到指定邮箱 - smtp.163.com

    1.简介: 服务器有时候是通过DHCP方式获取IP,一般服务器连个网线和电源就好了,要是每次开机还得连个显示器和键盘看看IP是多少就很不方便.懒人就让它自动发送个邮件.这里采用CentOS,163邮箱 ...

  7. win8.1解决鼠标右键反应慢的问题

    进入Win8注册表之后,我们依次展开: 位置:HKEY_CLASSES_ROOT\Directory\background\shellex\ContextMenuHandlers 之后,除了面的“Ne ...

  8. [Ubuntu][Linux]更改PATH路径

    1.什么是环境变量(PATH) 在Linux中,在执行命令时,系统会按照PATH的设置,去每个PATH定义的路径下搜索执行文件,先搜索到的文件先执行. 我们知道查阅文件属性的指令ls 完整文件名为:/ ...

  9. jQuery的$.get和$.ajax函数对比

    $.get较为简便,但在精细控制上乏力$.get(    url, // 请求的地址    {url:url,remark:remark},// 请求参数    function(data,textS ...

  10. JQuery实现click事件绑定与触发方法分析

    原生JS通过什么方法绑定click事件? 原生js有一下三种方法为DOM对象绑定click事件, 第一种,在html中添加 onclick属性,在此属性中添加要绑定的事件函数,如下, 这种方法为htm ...