python基础之函数,递归,内置函数
-
一、数学定义的函数与python中的函数
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域
例如y=2*x。
python中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中函数定义方法:
def test(x):
"The function definitions"
x+=1
return x
def:定义函数的关键字
test:函数名
():内可定义形参
"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值
调用运行:可以带参数也可以不带
方法:函数名()
test()
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。
-
二 为何使用函数
1.代码重用
2.保持一致性,易维护
3.可扩展性
-
三 函数和过程
过程定义:过程就是简单特殊没有返回值的函数。
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01(): pass def test02(): return 0 def test03(): return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'} t1=test01() t2=test02() t3=test03() print 'from test01 return is [%s]: ' %type(t1),t1 print 'from test02 return is [%s]: ' %type(t2),t2 print 'from test03 return is [%s]: ' %type(t3),t3
结果:
from test01 return is [<class 'NoneType'>]: None
from test02 return is [<class 'int'>]: 0
from test03 return is [<class 'tuple'>]: (0, 10, 'hello', ['alex', 'lb'], {'WuDaLang': 'lb'})
-
四 函数参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
4.默认参数
5.参数组

def test(x, *args): print(x) print(args)
test(1) test(1, 2, 3, 4, 5) test(1, {'name': 'alex'}) test(1, ['x', 'y', 'z']) test(1, *['x', 'y', 'z']) test(1, *{'name': 'alex'})
结果为:

def test(x, **kwargs): print(x) print(kwargs)
test(1, y = 2, z = 3) test(1, y = 2, z = 3, z = 4) #会报错,一个参数不能传两个值 test(1, **{'y': 1, 'z': 23})
结果为:

def test(x, *args, **kwargs): print(x) print(args) print(kwargs, kwargs.get('y')) test(1, 1, 3, 44, 2, x = 1, y = 2, z = 3) #报错 test(1, 1, 3, 44, 2, y = 2, z = 3) test(1, *[1, 3, 44, 2], **{'y': 1})
结果为:

-
五 局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
name='lhf' def change_name(): print('我的名字',name) change_name() def change_name(): name='帅了一笔' print('我的名字',name) change_name() print(name) def change_name(): global name name='帅了一笔' print('我的名字',name) change_name() print(name)
1、
name = 'lgh' def change_name(): #global name name = 'shuaileyibi' print('change_name', name) change_name() print(name) ———————————————— 结果为: change_name shuaileyibi lgh
name = 'lgh' def change_name(): global name name = 'shuaileyibi' print('change_name', name) change_name() print(name) ———————————————————— 结果为: change_name shuaileyibi shuaileyibi
2、
name = ['lgh', 'zs'] def change_name(): #global name name.append('shuaileyibi') print('change_name', name) change_name() print(name) —————————————————————— 结果为: change_name ['lgh', 'zs', 'shuaileyibi'] ['lgh', 'zs', 'shuaileyibi']
name = ['lgh', 'zs'] def change_name(): global name name.append('shuaileyibi') print('change_name', name) change_name() print(name) —————————————————————————— 结果为: change_name ['lgh', 'zs', 'shuaileyibi'] ['lgh', 'zs', 'shuaileyibi']
3、如果函数的内部无global关键字
--有声明局部变量
name = ['lgh', 'zs'] def change_name(): name = 'io' print('change_name', name) change_name() print(name) ———————————————— 结果为: change_name io ['lgh', 'zs']
--无声明局部变量
def change_name(): name.append('shuaileyibi') print('change_name', name) change_name() print(name) —————————————————— 结果为: change_name ['lgh', 'zs', 'shuaileyibi'] ['lgh', 'zs', 'shuaileyibi']
总结:
优先读取局部变量,只能读取全局变量,无法对全局变量重新赋值;
但是对于可变类型,可以对内部元素进行操作
4、如果函数中有global关键字,变量本质上就是全局变量,可读取可赋值
--有声明局部变量
name = ['lgh', 'zs'] def change_name(): global name name = 'io' print('change_name', name) change_name() print(name) ———————————————— 结果为: change_name io io
错误示例
name = ['lgh', 'zs'] def change_name(): name = 'io' global name print('change_name', name) change_name() print(name) —————————————— 报错
SyntaxError: name 'name' is assigned to before global declaration
--无声明局部变量
name = ['lgh', 'zs'] def change_name(): global name name.append('shuaileyibi') print('change_name', name) change_name() print(name) ———————————————— 结果为: change_name ['lgh', 'zs', 'shuaileyibi'] ['lgh', 'zs', 'shuaileyibi']
一般规定:
###### 全局变量变量名大写
###### 局部变量变量名小写
5、一些例子
#1
name = 'gy' def wh(): name = 'cz' def wwh(): global name name = 'lj' wwh() print(name)gy
print(name) wh() print(name)
————————————————
结果为:
cz
lj
#2
name = 'gy' def wh(): name = 'cz' def wwh(): nonlocal name #nonlocal,指代上一级的变量 name = 'lj' wwh() print(name) print(name) wh() print(name) ———————————————————— 结果为: gy lj gy
#3
name = 'gy' def wh(): nonlocal name name = 'lj' print('name1', name) print(name) wh() print(name) —————————————————— 报错: SyntaxError: no binding for nonlocal 'name' found
-
六 前向引用之'函数即变量'
def action(): print('in the action') logger() action() ———————————— 结果为: NameError: name 'logger' is not defined
def logger(): print('in the logger') def action(): print('in the action') logger() action() ———————————————— 结果为: in the action in the logger
def action(): print('in the action') logger() def logger(): print('in the logger') action() ———————————————— 结果为: in the action in the logger
-
七 嵌套函数和作用域
1、嵌套函数:在函数中再定义函数,或者函数的返回值是另一个函数的函数名
#1
name = 'alex' def foo(): name = 'lhf' def bar(): print(name) return bar foo() ———————————— 结果为: lhf
#2
def test1(): print('in the test1') def test(): print('in the test') return test1


#3
name = 'alex' def foo(): name = 'lhf' def bar(): #name = 'wpq' print(name) return bar

#4
name='alex' def foo(): name='lhf' def bar(): name='wupeiqi' def tt(): print(name) return tt return bar


-
八 递归调用
在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身,则称递归调用。
def calc(n): print(n) if int(n/2) == 0: return n return calc(int(n/2)) calc(10) ———————————————— 结果为: 10 5 2 1
import time person_list = ['alex', 'wpq', 'yh', 'lhf', 'zsc'] def ask_way(person_list): print('-'*60) if len(person_list) == 0: return print('根本没人知道') person = person_list.pop(0) if person == 'lhf': return '%s说:我知道。' %person print('hi [%s], 敢问路在何方' %person) print('%s回答道:我不知道,我帮你问问%s...' %(person, person_list)) time.sleep(1) res = ask_way(person_list) print('%s 问的结果是:%res' %(person, res)) return res res = ask_way(person_list) print(res) ———————————————————————————— 结果是: ------------------------------------------------------------ hi [alex], 敢问路在何方 alex回答道:我不知道,我帮你问问['wpq', 'yh', 'lhf', 'zsc']... ------------------------------------------------------------ hi [wpq], 敢问路在何方 wpq回答道:我不知道,我帮你问问['yh', 'lhf', 'zsc']... ------------------------------------------------------------ hi [yh], 敢问路在何方 yh回答道:我不知道,我帮你问问['lhf', 'zsc']... ------------------------------------------------------------ yh 问的结果是:'lhf说:我知道。'es wpq 问的结果是:'lhf说:我知道。'es alex 问的结果是:'lhf说:我知道。'es lhf说:我知道。
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
-
九 匿名函数
匿名函数就是不需要显式的指定函数
def calc(x): return x + 1 res = calc(10) print(res) —————————————————— 结果为: 11
lambda匿名函数:
func = lambda x: x + 1 print(func(10)) —————————————————————— 结果为: 11
name = 'alex'
#1函数式 def change_name(x): return x + '_sb' res = change_name(name) print(res) ———————————————————— 结果为: alex_sb
#2匿名函数式
f = lambda x: x+'_sb'
res = f(name)
print('匿名函数的运行结果', res)
————————————————————
结果为:
匿名函数的运行结果 alex_sb
多个参数的匿名函数:
func = lambda x, y, z: x + y + z print(func(1, 2, 3)) —————————————————— 结果为: 6
f = lambda x, y, z: (x + 1, y + 1, z + 1) #得自己加括号 print(f(2,3,4)) —————————————————— 结果为: (3, 4, 5)
匿名函数主要是和其它函数搭配使用,如下:
dic={'k1':10,'k2':100,'k3':30}
print(max(dic)) #取的是键的最大值
print(dic[max(dic,key=lambda k:dic[k])]) #传入匿名函数方法,取值的最大值的键,进而得到最大值
————————————————————
结果为:
k3
100
-
十 函数式编程
函数式编程又是面向过程的编程方式:
函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的函数,一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。
例如:
用户登录流程:前端接收处理用户请求-》将用户信息传给逻辑层,逻辑词处理用户信息-》将用户信息写入数据库
验证用户登录流程:数据库查询/处理用户信息-》交给逻辑层,逻辑层处理用户信息-》用户信息交给前端,前端显示用户信息
-
十一 高阶函数
满足以下两种之一的就是高阶函数:
1、把函数当做参数传给另外一个函数,即函数的传入参数是一个函数名
def foo(n): print(n) def bar(name): print('my name is %s' %name) foo(bar('alex')) ———————————————————— 结果为: my name is alex None
2、返回值中包含函数,即函数的返回值是一个函数名
#1
def bar(): print('from bar') def foo(): print('from foo') return bar n = foo() n() —————————————————————— 结果为: from foo from bar
#2
def handle(): print('from handle') return handle h = handle() h() ———————————————————— 结果为: from handle from handle
#3
def test1(): print('from test1') def test2(): print('from test2') return test1() #把test1的运行结果作为返回值 h = test2() —————————————————— 结果为: from test2 from test1
-
十二 函数补充——map,reduce,filter和format字符串格式化应用
-
1、map函数
#1 自定制初级map函数(逻辑函数写死的方法):给列表里的每个元素取乘方
num_l = [1, 2, 10, 5, 3, 7] def map_test(array): ret = [] for i in array: ret.append(i**2) return ret ret = map_test(num_l) print(ret) ———————————————— 结果为: [1, 4, 100, 25, 9, 49]
#2 自定制map函数(逻辑函数可变的方法)
num_l = [1, 2, 10, 5, 3, 7] #lambda x: x + 1 def add_one(x): return x + 1 #lambda x: x - 1 def sub_one(x): return x - 1 def map_test(func, array): ret = [] for i in array: res = func(i) ret.append(res) return ret print(map_test(add_one, num_l)) print(map_test(lambda x: x + 1, num_l)) print(map_test(sub_one, num_l)) print(map_test(lambda x: x - 1, num_l)) —————————————————— 结果为: [2, 3, 11, 6, 4, 8] [2, 3, 11, 6, 4, 8] [0, 1, 9, 4, 2, 6] [0, 1, 9, 4, 2, 6]
#3 map函数——map(func, iter)
num_l = [1, 2, 10, 5, 3, 7] #lambda x: x + 1 def add_one(x): return x + 1 #lambda x: x - 1 def sub_one(x): return x - 10 #传入匿名函数 res = map(lambda x: x + 1, num_l) print('内置函数map, 处理结果', res) #map的结果是一个可迭代对象 print(list(res)) ———————————————————— 结果为: 内置函数map, 处理结果 <map object at 0x000000B8DCFD8DD8> [2, 3, 11, 6, 4, 8] ============================================================ #传入有名函数 print('传的是有名函数', list(map(sub_one, num_l))) ———————————————————— 结果为: 传的是有名函数 [0, 1, 9, 4, 2, 6]
可迭代对象均可运用map
msg = 'lhf' print(list(map(lambda x: x.upper(), msg))) —————————————————————— 结果为: ['L', 'H', 'F']
-
2、filter函数
#1 自定制初级filter函数(逻辑函数写死的方法):筛选列表里的符合条件的元素
movie_people = ['sb_alex', 'sb_wpq', 'lhf', 'sb_yh'] def filter_test(array): ret = [] for p in array: if not p.startswith('sb'): ret.append(p) return ret res = filter_test(movie_people) print(res) —————————————————————— 结果为: ['lhf']
#2 自定制filter函数(逻辑函数可变的方法)
movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] def sb_show(n): return n.endswith('sb') def filter_test(func, array): ret = [] for p in array: if not func(p): ret.append(p) return ret res = filter_test(sb_show, movie_people) print(res) —————————————————————— 结果为: ['lhf']
#3 filter函数——filter(func, iter)
movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] def sb_show(n): return n.endswith('sb') #--->lambda n: n.endswith('sb') #传入有名函数 res = filter(sb_show, movie_people) print(res) print(list(res)) ———————————————————————— 结果为: <filter object at 0x000000AB22CEAE80> ['alex_sb', 'wpq_sb', 'yh_sb'] ==================================== #传入匿名函数 movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] print(list(filter(lambda n: not n.endswith('sb'), movie_people))) ———————————————————————— 结果为: ['lhf']
一个应用:在列表中筛选出年龄<=18的条目:
people = [ {'name': 'alex', 'age': 1000}, {'name': 'wpq', 'age': 10000}, {'name': 'yh', 'age': 9000}, {'name': 'lhf', 'age': 18} ]
print(list(filter(lambda p: p['age']<=18, people))) —————————————————————————— 结果为: [{'name': 'lhf', 'age': 18}]
-
3、reduce函数
#1 自定制初级reduce函数(逻辑函数写死的方法):处理一个序列,然后把序列进行合并操作
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(array): res = 0 for num in array: res += num return res print(reduce_test(num_l)) —————————————————— 结果为: 121
#2 自定制reduce函数(逻辑函数可变的方法)
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(func, array): res = array.pop(0) for num in array: res = func(res, num) return res print(reduce_test(lambda x, y: x * y, num_l)) ———————————————————————— 结果为: 72000
可传入初始值的自定制reduce函数:
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(func, array, init=None): if init is None: res = array.pop(0) else: res = init for num in array: res = func(res, num) return res print(reduce_test(lambda x, y: x * y, num_l, 100)) ———————————————————————————— 结果为: 7200000
#3 reduce函数——filter(func, iter, init=None)
from functools import reduce num_l = [1, 2, 3, 4, 5, 6, 100]
print(reduce(lambda x, y: x + y, num_l, 1)) ———————————————————————— 结果为: 122
小结:
map: 处理序列中的每个元素,得到的结果是一个‘列表’(迭代器),该‘列表’元素个数及位置与原来一样
filter: 遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来
reduce: 处理一个序列,然后把序列进行合并操作
-
4、format字符串格式化——'{}'.format()
#1 按顺序传值,不一一对应报错
tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')
print(tpl) ———————————————————————————— 结果为: i am seven, age 18, alex
#2 传入数字代表匹配的位置
tpl = "i am {2}, age {1}, {0}".format("seven", 18, 'alex') print(tpl) ———————————————————————————— 结果为: i am alex, age 18, seven ===================================== tpl = "i am {1}, age {1}".format("seven", 18, 'alex') print(tpl) ———————————————————————————— 结果为: i am 18, age 18
#3 传入'键值对'来进行匹配
1、通过"="的形式传值
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18) print(tpl) —————————————————————— 结果为: i am seven, age 18, really seven ======================================================================================== 2、通过字典的形式传值
tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18}) print(tpl) —————————————————————— 结果为: i am seven, age 18, really seven
#4 {}中可以添加一些特殊格式
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) print(tpl) ———————————————————————— 结果为: numbers: 1111,17,15,f,F, 1587.623000%
-
5、字符串应用之"%"

#1 %s可以代指字符串及其他数据结构


#2 %d只能代表数字格式

#3 %f代表浮点型,可以限制小数位数(%.2f等)


打印百分比

#4 通过键值对传值——如 “%(name)s,%(age)d” % {'name': 'alex', 'age': 18}

msg = 'i am \033[43:1m%(name)+10s\033[0m my hobby is alex' % {'name': 'lh'} print(msg)
补充:字符串拼接——print函数中的sep参数


浙公网安备 33010602011771号