一python中的函数

函数是逻辑结构化和过程化的一种编程方法。

python中函数定义方法:

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

二 为何使用函数

背景提要

现在老板让你写一个监控程序,监控服务器的系统状况,当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%:
发送邮件('内存报警')

总结使用函数的好处:

1.代码重用

2.保持一致性,易维护

3.可扩展性

三 函数和过程

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

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

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

总结:当一个函数/过程没有使用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

总结:

返回值数=0:返回None

返回值数=1:返回object

返回值数>1:返回tuple

四 函数是第一类对象

在python中所有的名字都没有储值功能

函数是第

 def foo():
print("yyp")
f1=foo
f1()
# 输出结果:
yyp

可以当做参数

 def foo():
print("tom") def func(msg):
print(msg)
msg() func(foo)
输出结果:
<function foo at 0x00000000020D3E18>
tom

可以当做返回值

 def foo():
print("tom") def func(msg):
return msg f=func(foo)
print(f)
f()
输出结果:
<function foo at 0x0000000002423E18>
tom

可以当做容器类型的一个元素

 def foo():
print("tom") func_dic={
'foo':foo
}
输出结果:
tom

一类对象指的是:函数可以被当做数据来处理被引用

五 函数参数

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

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

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

4.默认参数

5.参数组

六 局部变量和全局变量

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

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
 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)

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

 def action():
print 'in the action'
logger()
action()
报错NameError: global name 'logger' is not defined def 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 = "yyp"

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

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

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

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

 例一:
name='yyp' def foo():
name='sy'
def bar():
print(name)
return bar func=foo()
func() 例二:
name='yyp' def foo():
name='sy'
def bar():
name='tom'
def tt():
print(name)
return tt
return bar func=foo()
func()()

九 递归调用

 def calc(n):
print(n)
if int(n/2) ==0:
return n
return calc(int(n/2)) calc(10) 输出:
10
5
2
1
 #_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
import time person_list=['alex','wupeiqi','yuanhao','linhaifeng']
def ask_way(person_list):
print('-'*60)
if len(person_list) == 0:
return '没人知道'
person=person_list.pop(0)
if person == 'linhaifeng':
return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' %person
print('hi 美男[%s],敢问路在何方' %person)
print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' %(person,person_list))
time.sleep(3)
res=ask_way(person_list)
# print('%s问的结果是: %res' %(person,res))
return res res=ask_way(person_list) print(res)

递归问路

递归特性:

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

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

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

链接:堆栈扫盲

 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 it
print("找到数字",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 it
print("找到数字啦",dataset[0])
else:
print("没的分了,要找的数字[%s]不在列表里" % find_num) binary_search(data,66)

二分查找

十 匿名函数

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

 #这段代码
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

十一 函数式编程

函数式编程:

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 ret print(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 ret print(map_test(add_num,array))
#可以使用匿名函数
print(map_test(lambda x:x-1,array)) #上面就是map函数的功能,map得到的结果是可迭代对象
print(map(lambda x:x-1,range(5)))

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 res print(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=init
for i in l:
res=func(res,i)
return res print(reduce_test(lambda x,y:x+y,array))
print(reduce_test(lambda x,y:x+y,array,50))

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 ret print(filter_test(tell_sb,movie_people)) #函数filter,返回可迭代对象
print(filter(lambda x:x.startswith('sb'),movie_people))

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_list res=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)

总结

十二 内置函数

 字典的运算:最小值,最大值,排序
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 sequence sorted(iterable,key=None,reverse=False)

最新文章

  1. 协同开发中SVN的使用建议
  2. Ajax&amp;json
  3. Waiting Processed Cancelable ShowDialog (Release 2)
  4. [wechall] Time to Reset (Exploit, Coding, PHP)
  5. setTimeout()和setInterval() 何时被调用执行
  6. SQL Server 2005使用作业设置定时任务(转)
  7. IntelliJ IDEA 15 显示工具栏及底部周边工具栏
  8. Linux下glui 的安装,以及错误解决
  9. golang中channel的超时处理
  10. Prime Palindrome Golf
  11. Cocos2dx 3.0 过渡篇(三十一)ValueVector和Vector不得不说的故事
  12. Hibernate 系列教程13-继承-鉴别器与内连接相结合
  13. HDU 2859 Phalanx
  14. [自制操作系统] 图形界面&VBE工具&MMIO显存&图形库/字库
  15. swust oj 983
  16. 一种表达式语言的解析引擎JEXL简单使用
  17. oracle 索引扫描类型的分类与构造
  18. CSS 尺寸 (Dimension) 实例
  19. asdasda
  20. 【Jmeter自学】Jmeter性能测试(四)

热门文章

  1. 前端(Node.js)(2)-- Node.js开发环境配置
  2. Java问题解读系列之IO相关---Java深拷贝和浅拷贝
  3. tesseract训练手写体
  4. Neo4j系列-简介及应用场景
  5. 出现$(#form).validate is not a function的问题
  6. Nginx 函数解析之ngx_http_get_forwarded_addr_internal
  7. 微信小程序-- WXML语法
  8. 微信小程序开发之图片等比例缩放 获取屏幕尺寸图片尺寸 自适应
  9. springboot整合neo4j
  10. DirectX11笔记(二)--Direct3D初始化1之基本概念