2-1
函数的定义
python的代码运行是从上往下运行,用很长的一段代码来实现一个功能。
如果在另一个位置又需要完成这个功能,不断的复制粘贴代码显然不符合python的编程思想。
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段,还能提高代码的重复利用率。
python自带许多内置函数,比如print()打印函数,str()函数可以将任意对象转换成字符串类型。
下面介绍如何自己完成某一个功能的函数,对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来,调用者无需了解。这也是python开发效率高的一个重要原因。
2-2
函数的语法
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
1def a():
2 print('我是函数A,我开始运行')
如上就是一个函数的固定格式,定义的函数名为a。
2-3
函数的调用
写完一个函数后,运行代码函数的内容并不会运行,必须要手动调用才会运行,这也方便我们可以在任何位置调用这个函数然后再运行。
1def a():
2 print('我是函数A,我开始运行')
3
4运行结果>>>我是函数A,我开始运行
5
6def a():
7 print('我是函数A,我开始运行')
8a()
9
10运行结果>>>我是函数A,我开始运行
函数的运行方法即 函数名加上括号即可运行。
2-4
函数传递参数
Python的函数定义非常简单,但灵活度却非常大。
下面介绍python函数传参,传参指的是将你传入的数据放到函数中执行。
1def a(b):
2 print('我是函数A,我传入的参数是:{}'.format(b))
3b=1
4a(b)
5
6运行结果>>>我是函数A,我传入的参数是:2
非常的灵活与简便。
Python函数支持默认参数,即可以给函数的参数指定默认值。当该参数没有传入相应的值时,该参数就使用默认值。
1def a(b,c=1)
2 print('B的数值为:{}'.format(b))
3 print('C的数值为:{}'.format(c))
4a(2)
5B的数值为:2
6C的数值为:1
当我们调用a(2),就相当于调用a(2,1)。
-
设置默认参数时,必选参数在前,默认参数在后,否则Python的解释器会报错;
-
定义默认参数要牢记:默认参数必须指向不可变对象!
2-5
函数返回结果
函数不仅能处理一段业务逻辑,还能返回一个结果,具体语法如下:
1def a(b):
2 return b
3c = a(1)
4print(c)
5
6运行结果>>>1
返回使用的return,上面代码的功能是返回传入的值。
需要注意,return一但返回,这个函数就算运行完毕了,也就是说后面代码都不会继续运行,相当于使用return中断函数。
2-6
异常的处理
python使用try和except来处理python程序在运行中出现的异常和错误,比如你将数字与字符串相加就会出现异常,那么使用try+except来处理异常
固定的格式如下:
1try:
2 print(100+'学习')
3except:
4 print('代码出错')
5运行结果>>>代码出错
除了出错处理,还要知道出错原因,使用Exception即可获取出错原因
1try:
2 运行代码1
3except Exception as e:
4 print('错误原因为:{}'.format(str(e)))
异常处理常用在网络请求失败,打开文件异常等许多情况下。
-
当你掌握函数后,在你以后几乎所有的代码中,都会使用到函数式编程
-
使用函数能将功能块更加独立开来,同时代码更加简介直观,还可以反复多次调用代码块
-
举个最小的案例,你在写网络爬虫的时候,可以定义多个函数,分别负责抓数据,洗数据,保存数据的功能,最后调用分配即可
-
了解函数的定义,即将代码块集成在一个点上,需要的时候直接调用这个点就能调用这个代码块
-
函数的固定格式,使用def()开头,加冒号
-
函数的调用方法,即当你写好函数后,使用()即可调用运行函数
-
函数的参数传递,写函数的时候,提供传递参数的位置,可以让函数功能更加多样化
-
函数正常是返回None,如果你使用关键词return返回数据,那么这个函数就可以返回需要的数据,return还能直接中断函数后面的代码运行
-
使用try/except做异常处理,当你遇到可能存在异常的时候,比如错误的数据相加,删除不存在的文件,网络请求超时等,使用异常处理就能让你的异常位置得到处理,不会直接报错停止运行代码
普通传参的小坑
1def test(a=[]):
2 a.append('A')
3 return a
4print test()
5print test()
6print test()
返回的结果:
1['A']
2['A', 'A']
3['A', 'A', 'A']
原因:传入的参数是一个空的列表,Python遇到函数的时候会把函数读到内存中,默认参数会被创建。虽然函数没有执行,但是其中赋值创建变量,并且创建好了。a始终没有改变,指向的内存方向都是同一个内存。
使用id()可以查看函数内部在内存中的地址。
1def test(a=[]):
2 a.append('A')
3 print(id(a))
4 return a
5print test()
6print test()
7print test()
返回结果:
153854536
2['A']
353854536
4['A', 'A']
553854536
6['A', 'A', 'A']
可以看到指向内存的位置都没变。
这里引申一下Python的可变对象和不可变对象,dict,list是可变对象,str,int,tuple,float是不可变对象。意思就是可变对象的值改变后对应的内存地址没改变。但是不可变对象改变数值后,就会创立一个新的对象并且占用新的内存空间。所以一般如果想要把一个列表的所有元素拼接成一个字符串的话,遍历这个列表没然后使用''.join()方法,节省内存。
如果想要每次都是变成空的列表可以这样写。
1def test_new(a=None):
2 if a is None:
3 a=[]
4 a.append('A')
5 print id(a)
6 return a
7print(test_new())
8print(test_new())
9print(test_new())
记住,对应的内存地址任然是一样的。
返回结果:
151934344
2['A']
351934344
4['A']
551934344
6['A']
动态参数
Python的动态参数有*args与**kwargs。*args表示任何多个无名参数,它是一个tuple。**kwargs表示关键字参数,它是一个dict。
*args的用法
1def fun(*args):
2 for x in args:
3 print(x)
4fun(1,2,3)
返回结果:
11
22
33
当然还可以传入列表,但是传入列表的时候必须要在前面加上*号。比如:
1li=[1,2,3,4,5]
2fun(*li)
返回结果:
11
22
33
44
55
**kwargs的用法
1def fun_test(**kwargs):
2 for x in kwargs:
3 print (x,kwargs[x])
4fun_test(k1=1,k2=[1,2,3])
返回结果:
1k2 [1, 2, 3]
2k1 1
当然还可以传入字典,使用方法和上面一致,也是加上两个*号。
递归定义
递归函数:这个函数在他的内部调用了自身。函数自己调用自己,实现递归。
递归特性:
-
记住所有的递归函数都有一个退出条件
-
相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入)。
-
递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
普通算法实现高斯求和:
1def sum(munber):
2 total=0
3 for i in range(1,munber+1):
4 total+=i
5 return total
6print(sum(100)s)
运行结果:
15050
如果使用递归方法:
1def sum_number(number):
2 if number==0:
3 return False
4 return sum_number(number-1)+number
5 # 第一次是sum_number(99)+100的值
6 # 第二次是sum_number(98)+99的值
7 # 最后一个是sum_number(0)
8print(sum_number(100))
运行结果:
15050
递归小坑
在写百度子域名采集的时候,因为百度经常会返回一些失败的页面,所以需要对访问百度的函数进行递归操作,直到返回正确的页面。但是发现在递归函数得到正确页面,返回的结果却是None,找了一下资料,才明白递归的本质原理是酱紫的:
主要的原因是函数调用中的堆栈进出顺序,比如:
1运行递归函数1
2函数1不是想要的结果...
3运行递归函数2
4函数2不是想要的结果....
5运行递归函数3
6递归函数3是想要的结果...
7准备返回函数3的结果
8函数3的结果返回到函数2
9函数2没有想要的结果....
10返回None
解决方法是返回递归函数的返回结果
1即在函数1不是想要的结果.....
2执行函数2的时候.....
3返回函数1
用代码写出来就是
1def test(x):
2 if x<10:
3 x+=1
4 test(x)
5 else:
6 return x
改成
1def test(x):
2 if x<10:
3 x+=1
4 return test(x)
5 else:
6 return x
往期推荐
本文始发于微信公众号(安全研发):Python安全开发之函数编程【C08课】
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论