一 数学定义的函数与python中的函数

初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域

例如y=2*x

python中函数定义:函数是逻辑结构化和过程化的一种编程方法。

python中函数定义方法:def test(x):"The function definitions"x+=1return xdef:定义函数的关键字
test:函数名
():内可定义形参
"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值调用运行:可以带参数也可以不带
函数名()

补充:

1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)

2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。

二 为何使用函数

背景提要

现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码

while True:if cpu利用率 > 90%:#发送邮件提醒
        连接邮箱服务器发送邮件关闭连接if 硬盘使用空间 > 90%:#发送邮件提醒
        连接邮箱服务器发送邮件关闭连接if 内存占用 > 80%:#发送邮件提醒
        连接邮箱服务器发送邮件关闭连接

上面的代码实现了功能,但即使是邻居老王也看出了端倪,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:

  1. 代码重复过多,一个劲的copy and paste不符合高端程序员的气质
  2. 如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍

你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下

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

你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,心想,老王这个人真是不一般,突然对他的背景更感兴趣了,问老王,这些花式玩法你都是怎么知道的? 老王亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲,“老夫,年少时,师从京西沙河淫魔银角大王 ”, 你一听“银角大王”这几个字,不由的娇躯一震,心想,真nb,怪不得代码写的这么6, 这“银角大王”当年在江湖上可是数得着的响当当的名字,只可惜后期纵欲过度,卒于公元2016年, 真是可惜了,只留下其哥哥孤守当年兄弟俩一起打下来的江山。 此时你看着的老王离开的身影,感觉你儿子跟他越来越像了。。。

总结使用函数的好处:

1.代码重用

2.保持一致性,易维护

3.可扩展性

三 函数和过程

过程定义:过程就是简单特殊没有返回值的函数

这么看来我们在讨论为何使用函数的的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在python中有比较神奇的事情

def test01():msg='hello The little green frog'print msgdef test02():msg='hello WuDaLang'print msgreturn msgt1=test01()t2=test02()print 'from test01 return is [%s]' %t1
print 'from test02 return is [%s]' %t2

总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,

所以在python中即便是过程也可以算作函数。

def test01():passdef test02():return 0def 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

总结:

返回值数=0:返回None

返回值数=1:返回object

返回值数>1:返回tuple

四 函数参数

1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)

4.默认参数

5.参数组

def test(x,*args,**kwargs):print(x)print(args)print(kwargs)
test(1,2,3,5,432,4,y=2,z=3)    输出结果:1
(2, 3, 5, 432, 4)
{'y': 2, 'z': 3}

五 局部变量和全局变量

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
name='lhf'def change_name():print('我的名字',name)change_name()def change_name():name='帅了一笔'print('我的名字',name)change_name()
print(name)def change_name():global namename='帅了一笔'print('我的名字',name)change_name()
print(name)

六 前向引用之'函数即变量'

def action():print 'in the action'logger()
action()
报错NameError: global name 'logger' is not defineddef logger():print 'in the logger'
def action():print 'in the action'logger()action()def action():print 'in the action'logger()
def logger():print 'in the logger'action()

七 嵌套函数和作用域

看上面的标题的意思是,函数还能套函数?of course

name = "Alex"def change_name():name = "Alex2"def change_name2():name = "Alex3"print("第3层打印",name)change_name2() #调用内层函数print("第2层打印",name)change_name()
print("最外层打印",name)

此时,在最外层调用change_name2()会出现什么效果?

没错, 出错了, 为什么呢?

作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变

例一:
name='alex'def foo():name='lhf'def bar():print(name)return barfunc=foo()
func()例二:
name='alex'def foo():name='lhf'def bar():name='wupeiqi'def tt():print(name)return ttreturn barfunc=foo()
func()()

八 递归调用

古之欲明明德于天下者,先治其国;欲治其国者,先齐其家;欲齐其家者,先修其身;欲修其身者,先正其心;欲正其心者,先诚其意;欲诚其意者,先致其知,致知在格物。物格而后知至,知至而后意诚,意诚而后心正,心正而后身修,身修而后家齐,家齐而后国治,国治而后天下平。

在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身

def calc(n):print(n)if int(n/2) ==0:return nreturn calc(int(n/2))calc(10)输出:
10
5
2
1

递归特性:

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html 

尾递归优化:http://egon09.blog.51cto.com/9161406/1842475

data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]def binary_search(dataset,find_num):print(dataset)if len(dataset) >1:mid = int(len(dataset)/2)if dataset[mid] == find_num:  #find itprint("找到数字",dataset[mid])elif dataset[mid] > find_num :# 找的数在mid左面print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid])return binary_search(dataset[0:mid], find_num)else:# 找的数在mid右面print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid])return binary_search(dataset[mid+1:],find_num)else:if dataset[0] == find_num:  #find itprint("找到数字啦",dataset[0])else:print("没的分了,要找的数字[%s]不在列表里" % find_num)binary_search(data,66)二分查找

View Code

九 匿名函数

匿名函数就是不需要显式的指定函数

#这段代码
def calc(n):return n**n
print(calc(10))#换成匿名函数
calc = lambda n:n**n
print(calc(10))

你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下

l=[3,2,100,999,213,1111,31121,333]
print(max(l))dic={'k1':10,'k2':100,'k3':30}print(max(dic))
print(dic[max(dic,key=lambda k:dic[k])])

res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:print(i)输出
1
25
49
16
64

十 函数式编程

峰哥原创面向过程解释:

函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的函数,一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。

例如:
用户登录流程:前端接收处理用户请求-》将用户信息传给逻辑层,逻辑词处理用户信息-》将用户信息写入数据库
验证用户登录流程:数据库查询/处理用户信息-》交给逻辑层,逻辑层处理用户信息-》用户信息交给前端,前端显示用户信息

函数式编程:

http://egon09.blog.51cto.com/9161406/1842475

11 高阶函数

满足俩个特性任意一个即为高阶函数

1.函数的传入参数是一个函数名

2.函数的返回值是一个函数名

array=[1,3,4,71,2]ret=[]
for i in array:ret.append(i**2)
print(ret)#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数
def map_test(array):ret=[]for i in array:ret.append(i**2)return retprint(map_test(array))#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样
def add_num(x):return x+1
def map_test(func,array):ret=[]for i in array:ret.append(func(i))return retprint(map_test(add_num,array))
#可以使用匿名函数
print(map_test(lambda x:x-1,array))#上面就是map函数的功能,map得到的结果是可迭代对象
print(map(lambda x:x-1,range(5)))map函数

map函数

from functools import reduce
#合并,得一个合并的结果
array_test=[1,2,3,4,5,6,7]
array=range(100)#报错啊,res没有指定初始值
def reduce_test(func,array):l=list(array)for i in l:res=func(res,i)return res# print(reduce_test(lambda x,y:x+y,array))#可以从列表左边弹出第一个值
def reduce_test(func,array):l=list(array)res=l.pop(0)for i in l:res=func(res,i)return resprint(reduce_test(lambda x,y:x+y,array))#我们应该支持用户自己传入初始值
def reduce_test(func,array,init=None):l=list(array)if init is None:res=l.pop(0)else:res=initfor i in l:res=func(res,i)return resprint(reduce_test(lambda x,y:x+y,array))
print(reduce_test(lambda x,y:x+y,array,50))reduce函数

reduce函数

#电影院聚集了一群看电影bb的傻逼,让我们找出他们
movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']def tell_sb(x):return x.startswith('sb')def filter_test(func,array):ret=[]for i in array:if func(i):ret.append(i)return retprint(filter_test(tell_sb,movie_people))#函数filter,返回可迭代对象
print(filter(lambda x:x.startswith('sb'),movie_people))filter函数

filter函数

#当然了,map,filter,reduce,可以处理所有数据类型

name_dic=[{'name':'alex','age':1000},{'name':'wupeiqi','age':10000},{'name':'yuanhao','age':9000},{'name':'linhaifeng','age':18},
]
#利用filter过滤掉千年王八,万年龟,还有一个九千岁
def func(x):age_list=[1000,10000,9000]return x['age'] not in age_listres=filter(func,name_dic)
for i in res:print(i)res=filter(lambda x:x['age'] == 18,name_dic)
for i in res:print(i)#reduce用来计算1到100的和
from functools import reduce
print(reduce(lambda x,y:x+y,range(100),100))
print(reduce(lambda x,y:x+y,range(1,101)))#用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sb
name=['alex','wupeiqi','yuanhao']res=map(lambda x:x+'_sb',name)
for i in res:print(i)总结

总结

小结:

# map()# 处理序列中的每一个元素,得到的结果是一个‘列表’(即可迭代对象),该‘列表’元素的个数及位置与原来的一样

#filter#遍历序列中的每个元素,判断每个元素得到的布尔值,如果是True则留下来
people =[{'name':'alex','age':10000},{'name':'wuqi','age':5000},{'name':'wangwang','age':3000},{'name':'meimei','age':20}
]
v =list(filter(lambda p:p['age']<=20,people))
print(v)    #[{'name': 'meimei', 'age': 20}]

#reduce#引入文件  from functools import reduce#处理一个序列,然后把序列进行合并操作
from functools import reduce
print(reduce(lambda x,y:x+y,range(100),100))  #5050   后面的设定初始值100
print(reduce(lambda x,y:x+y,range(1,100)))    #4950   左开,右闭区间

十一 内置函数

字典的运算:最小值,最大值,排序
salaries={'egon':3000,'alex':100000000,'wupeiqi':10000,'yuanhao':2000
}迭代字典,取得是key,因而比较的是key的最大和最小值
>>> max(salaries)
'yuanhao'
>>> min(salaries)
'alex'可以取values,来比较
>>> max(salaries.values())
>>> min(salaries.values())
但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
>>> max(salaries,key=lambda k:salary[k])
'alex'
>>> min(salaries,key=lambda k:salary[k])
'yuanhao'也可以通过zip的方式实现
salaries_and_names=zip(salaries.values(),salaries.keys()) 先比较值,值相同则比较键
>>> max(salaries_and_names)
(100000000, 'alex')salaries_and_names是迭代器,因而只能访问一次
>>> min(salaries_and_names)
Traceback (most recent call last):File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequencesorted(iterable,key=None,reverse=False)

View Code

内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii

十二 本节作业

有以下员工信息表

当然此表你在文件存储时可以这样表示

1 1,Alex Li,22,13651054608,IT,2013-04-01

现需要对这个员工信息文件,实现增删改查操作

  1. 可进行模糊查询,语法至少支持下面3种:可创建新员工纪录,以phone做唯一键,staff_id需自增

    1.   select name,age from staff_table where age > 22
    2.   select  * from staff_table where dept = "IT"
    3. select  * from staff_table where enroll_date like "2013"
    4. 查到的信息,打印后,最后面还要显示查到的条数
  2. 可删除指定员工信息纪录,输入员工id,即可删除
  3. 可修改员工信息,语法如下:
    1.   UPDATE staff_table SET dept="Market" WHERE where dept = "IT"

 注意:以上需求,要充分使用函数,请尽你的最大限度来减少重复代码!

内置函数
匿名函数
递归
=====================作业一
#用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sb
name=['alex','wupeiqi','yuanhao']#用map来处理下述l,然后用list得到一个新的列表,列表中每个人的名字都是sb结尾
>>> l=[{'name':'alex'},{'name':'y'}]
>>> x=map(lambda i:{'name':i['name']+'sb'},l)
>>> for i in x:
...  print(i)
...
{'name': 'alexsb'}
{'name': 'ysb'}=====================作业二
#用filter来处理,得到股票价格大于20的股票名字
shares={'IBM':36.6,'Lenovo':23.2,'oldboy':21.2,'ocean':10.2,
}
>>> f=filter(lambda k:shares[k]>20,shares)
>>> list(f)
['IBM', 'Lenovo', 'oldboy']=====================作业三
#如下,每个小字典的name对应股票名字,shares对应多少股,price对应股票的价格
portfolio = [{'name': 'IBM', 'shares': 100, 'price': 91.1},{'name': 'AAPL', 'shares': 50, 'price': 543.22},{'name': 'FB', 'shares': 200, 'price': 21.09},{'name': 'HPQ', 'shares': 35, 'price': 31.75},{'name': 'YHOO', 'shares': 45, 'price': 16.35},{'name': 'ACME', 'shares': 75, 'price': 115.65}
]1:map来得出一个包含数字的迭代器,数字指的是:购买每支股票的总价格
>>> m=map(lambda item:item['shares']*item['price'],l)2:基于1的结果,用reduce来计算,购买这些股票总共花了多少钱
>>> r=reduce(lambda x,y:x+y,m)
>>> r
51009.753:用filter过滤出,单价大于100的股票有哪些
>>> f=filter(lambda item:item['price'] > 100,l)

View Code

函数总结:

形参

  普通参数必须一一对应,必须传

  默认参数可传可不传   实参的级别大于形参级别,

  一个形参只能给它传一次,不能被赋予多个值

  *args 处理关键字、**字典,其他都可以传,它是一个元组,不传也可以

  **kwargs只能接收关键字参数,如果接收字典的话,在字典前面要加**,不传也可以

  优先级别 先是位置一一对应,普通参数,默认参数,*参数,**参数

实参

  普通参数必须一一对应,必须传

转载于:https://www.cnblogs.com/kangming-/p/9865648.html

python全栈开发笔记---------函数相关推荐

  1. Python全栈开发之函数

    No.1 函数介绍 所谓函数,就是把具有独立功能的代码块组织为一个小模块,在需要的时候调用 函数的使用有两个步骤: 1.定义函数 2.调用函数 函数的作用,代码重用,提高开发效率 No.2 定义和调用 ...

  2. python全栈开发笔记--------条件语句

    Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false. Py ...

  3. python全栈开发_day10_函数的实参和形参

    一:函数的实参和形参 实参是在调用函数时()出现的外界的实际的值 形参不能再函数外部直接使用 1)实参的两种形式 实参是调用函数时()中传入的参数 1.位置实参 def a(a):print(a)a( ...

  4. python全栈开发笔记---基本数据类型--数字型魔法

    数字  int a1 =123a2=456 int 讲字符串转换为数字 a = "123" #字符串 b = int(a) #将字符串转换成整形b = b + 1000 #只有整形 ...

  5. python全栈开发笔记---------数据类型-----集合set

    定义:由不同元素组成的集合,集合中是一组无序排列的可hash值,可以作为字典的key 1.不同元素组成 2.无序 3.集合中元素必须是不可变类型(数字,字符串,元组) 特性:集合的目的是讲不同的值放到 ...

  6. python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)

    python全栈开发笔记第二模块 第四章 :常用模块(第二部分)     一.os 模块的 详解 1.os.getcwd()    :得到当前工作目录,即当前python解释器所在目录路径 impor ...

  7. python全栈开发中级班全程笔记(第三模块、第一章(1.面向对象基础))

    python全栈开发笔记第三模块           第一部分 第一章 :面向对象(类) 一.面向过程编程1.面向过程编程:主要是过程二字,所谓过程,就是指解决问题的步骤,也可以说是设计一套流水线(机 ...

  8. 学习笔记之Python全栈开发/人工智能公开课_腾讯课堂

    Python全栈开发/人工智能公开课_腾讯课堂 https://ke.qq.com/course/190378 https://github.com/haoran119/ke.qq.com.pytho ...

  9. Python全栈开发【基础-09】深浅拷贝+while循环

    专栏介绍: 本专栏为Python全栈开发系列文章,技术包括Python基础.函数.文件.面向对象.网络编程.并发编程.MySQL数据库.HTML.JavaScript.CSS.JQuery.boots ...

最新文章

  1. Binder Driver浅析:Binder线程池
  2. 多进程多线程处理文本数据
  3. 手动创建servlet
  4. python注册人工智能专业_从专业程度上分析Python和人工智能(AI) 它们如何相关?...
  5. Asp.Net就业课之三验证控件
  6. php网站xml链接,xml图像超链接的制作代码
  7. 平衡二叉树AVL删除
  8. Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析
  9. java加vue实例_Vue.Js及Java实现文件分片上传代码实例
  10. codevs4919 线段树练习4
  11. (Python)计算器的设计与实现
  12. 对三极管特性曲线的理解
  13. 城市数据大脑:小汽车儿堵成翔?NONONO!
  14. RabbitMQ-Plugin configuration unchanged
  15. Tensorflow的基本使用方法
  16. 零钱兑换问题c语言编程,leetcode- 零钱兑换 II(背包问题-总结-复盘)
  17. 帮我们找房租房买房的代理模式
  18. SwrContext重采样结构体--swr_alloc()、swr_init()、swr_free()
  19. Excel 2010 VBA 入门 095 数据处理之用数组实现分列
  20. re2c源码下载及编译

热门文章

  1. CxImage图像处理类库
  2. 【Go】Go基础(九):接口(Interfaces)与反射(reflection)
  3. php 开发restful api,用PHP创建RESTful API?
  4. 慈溪计算机编程培训,慈溪Python编程培训
  5. python病毒扫描器_基于Python的病毒扫描机制
  6. Mybatis入门:2(xml形式的增删改查)
  7. 随机森林 java_机器学习weka,java api调用随机森林及保存模型
  8. 投影转换_即插即用,办公投影不用愁:毕亚兹Mini DP转HDMIVGA转换器
  9. SSM实现网上商城 有聊天功能
  10. java 套接字关联的通道_Java 通道教程 – NIO 2.0