函数
def foo3():#函数名与参数
#函数体
cumsum=0
for i in range(15):
cumsum+=i
#return返回的是对象,(如返回对象数>1返回元组)
return cumsum,cumsum*2
return cumsum-1 #不返回
生成器
##yield 生成器
def foo4():
for i in range(5):
yield i
yield 'f' #再加入一个yield看看会不会被执行
i+=1
g1=foo4()#返回(generator object foo4 at 0x0000000002555E60)
type(g1)#<class 'generator'>
next(g1)#继续上一次的位置,进入下一层循环
#执行完最后一次循环,结束 yield语句并抛出StopIteration 异常
函数的参数
- 位置参数
- 关键字参数
- 位置参数包裹*
- 关键字参数包裹**
##位置参数
def foo3(companyName,websiteUrl):#位置参数的定义
print('公司名:',companyName,'公司网址:',websiteUrl)
foo3('七月在线','http://www.julyedu.com')
foo3('http://www.julyedu.com',websiteUrl='七月在线')
#位置参数,对位置敏感,传递时不用指定参数名
##关键字参数
def foo4(companyName,websiteUrl,intro='专注AI教育'):#关键字参数的定义
print('公司名:',companyName,'公司网址:',websiteUrl,'介绍:',intro)
foo4('七月在线','http://www.julyedu.com')#不传关键字参数,函数依旧可以被调用,采用默认值
foo4('七月在线','http://www.julyedu.com',intro='国内领先的AI教育平台')#传关键字参数,覆盖默认值
##位置参数包裹*
def mysum1(a,b,c):
return a+b+c
mysum1(5,7,15)
#mysum1(5,7) #报错,因为传入的参数少于函数定义时的个数
#mysum1(5,7,15,22) #报错,因为传入的参数多于函数定义时的个数
#这时我们就需要使用包裹进行接收
def mysum2(*args):
print(type(args)) # #<class 'tuple'>
return sum(args)
mysum2(5,7,15,22,33)#正常调用
mysum2(5,7)#正常调用
#传递参数时使用包裹-位置参数
l1=[1,5,6,7,2,5,3.5,9,3,4]
mysum2(*l1) #将列表打碎 每一个元素是一个tuple 返回的是(1,5,6,7,2,5,3,5,9,3,4)
#zip案例
l1=[(1,3),(2,4)]
list(zip(*l1)) #将列表l1打碎 再拼接起来
##那同样如果想一次性传入不定长关键字参数,也可以使用一个包裹进行接收
##关键字参数包裹**
def filmInfo(**kwargs):
print(type(kwargs)) #<class 'dict'>
for key,values in kwargs.items():
print(key,':',values)
filmInfo(film='羞羞的铁拳',box=3.5)
filmInfo(film='羞羞的铁拳',box=3.5,rate=7.9)
d1={'羞羞的铁拳':3.5,'雷神3':3.1,'战狼2':60} #一定要注意字典和关键字参数传入的不同
filmInfo(**d1)
#包裹解包顺序
#首先拆位置参数包裹,按顺序给必选,默认,可变。
#再抓给关键字参数包裹
def scoreReport(name,age,*args,course='python',**kwargs):
print('个人信息:',name,age)
for item in args:
print(item)
print('课程信息:',course)
print('每节课成绩:')
for key,value in kwargs.items():
print (key,value)
scoreReport('xiaoming',22,'高中部','三年二班',Lesson1=80,Lesson2=85)
scoreReport('xiaoming',22,'三年二班',course='machine learning',Lesson1=80,Lesson2=85)
参数传递的处理
重要
##值传递,参数本身不会被修改
a=7
b='julyedu'
print('before reference:',a,b)
def foo1(a,b):
a+=1
b+='.com'
print('In foo1 a,b has changed to',a,b)
foo1(a,b)
print('after reference:',a,b) #after reference: 7 julyedu #非常重要
#结论:值传递时,变量传递给函数后,函数复制一份,不会影响原有变量
##指针传递参数,会修改参数本身
l1=[1,2,3.4]
d1={'name':'jack'}
def foo2(a,b):
a.pop()
b['age']=22
print('before reference:',l1,d1) #before reference: [1, 2, 3.4] {'name': 'jack'}
foo2(l1,d1)
print('after reference:',l1,d1) #after reference: [1, 2] {'name': 'jack', 'age': 22}
#结论:指针(或引用)传递时,变量传递给函数的是及引用,该引用可以改变原变量
变量的作用域
全局变量
局部变量
局部变量可以覆盖全局变量
局部作用域->全局作用域
偏函数PFA
使用场景:如果一个函数的参数很多,而在每次调用的时候有一些又经常不需要被指定时,就可以使用偏函数(近似理解为默认值)
语法:partical(func,*args,**keywords)
使用:from functools import partial
import functools
#Partial function application(PFA)
# 只设置了一部分的参数的函数
# 固定一部分参数,使得被调用时,某些参数被固定住了。
#例如我们要定义一个函数将传进来的16进制的字符串,转换为10进制的
def hex2int(num):
return int(str(num),base=16)#base为关键字参数,这个在调用int这个函数时,固定给16。因为这个函数就是用来转换16进制到10进制
hex2int('F')#这时调用,相当于实际上会把10作为*args的一部分自动加到左边,也就是:int('F',base=16),这样就少写了一个函数
#这时也可以使用偏函数,固定int函数的关键字参数base,可以这样定义:
import functools
hex2int2=functools.partial(int,base=16)
hex2int2('A') #10
#偏函数可以固定位置参数
max100=functools.partial(max,100)#定义一个叫max100的偏函数,将这个偏函数的第一个值固定为100
max100(101)#这时调用它,传入的值,都会与100进行比较反并返回。
type(max100)#偏函数的类型与普通函数不一样 #<class 'functools.partial'>
递归函数
#递归的方法求一个列表中数值的累加
def foo1(num):
if len(num)==1:
return num[0]
else:
return num[0]+foo1(num[1:]) #切片
foo1([1,2,31,5,6,55]) #100
#使用递归分解质因数
l1=[]
def fenji(num):
num=int(num)
for i in range(2,num):
if num%i==0:
l1.append(i)
nextv=int(num/i)
fenji(nextv)
break#这里的break不加就会硬循环60次
return l1
fenji(60)
#阶乘
def factorial(n):
if n==1:
return 1
else:
return n*factorial(n-1)
factorial (5)
匿名函数lambda
#匿名函数
print(type(lambda a,b:a**b )) #function
#不用写return
#使用1:作为正常函数使用,不推荐
foo=lambda x,y:x+y #不用写return
print(foo(5,6)) #11
#使用2:lambda关键字定义在高阶函数的参数位上
d1={'china':15,'India':9,'USA':2,'Japan':1.5}
sorted(d1.items(),key=lambda x:(x[0],x[1]))#按d1.items()第0个元素升序,国家名
# sorted(d1.items(),key=lambda x:(x[1]))#按d1.items()第1个元素升序,人口数
高阶函数
函数名可以向变量一样,在函数中作为参数,传来传去
##高阶函数
def mycalucate(num,func):
return func #num作为参数再传入func中
l1=[5,8,3,6,9,15,22]
mycalucate(l1,max)
mycalucate(l1,min)
mycalucate(l1,sum)
mycalucate(l1,reversed)
##回调函数
#函数作为调用函数的结果返回
def callbackfunc(*num):
return max #返回的是函数 所以叫回调函数
list(callbackfunc(53,5,33)) #53
BIFs-高阶函数
filter:对每个元素做过滤
map:对每个元素做映射 一种更高级的列表推导式
reduce:两两传给func
Python 3.x中,reduce()函数已经被从全局名字 空间里移除了,它和partical一样被放置在fucntools模块中。使用前需要调用
l1=[2,3,5,7,3,4,5,9,'julyedu.com',[2,3,3],5,2]
##filter
#语法:filter(function,list)
# 函数 f 的作用是对每个元素进行判断,返回 True或 False
# filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
def myfilter(x):
if x>60:
return True
else:
return False
filter(myfilter,l1)
list(filter(lambda x:True if type(x)==str else False,l1))
##map
# 语法:map(function, list)
#让list的每一个元素依次调用function函数,并获取返回值存入一个新的list中。
map(lambda x:(x,l1.count(x)),l1) #统计列表中每个元素出现的次数 输出(x,它出现的次数)
## reduce
# 语法:reduce(function, list)
#函数function必须包含两个参数,optional可选,如果存在则表示初值为optional
#reduce()对list的每个元素反复调用函数f,并返回最终结果值。
from functools import reduce
reduce(lambda a,b:a+b,[1,2,3,4,5,6,7,8]) #lambda输入的是两个参数 输出的是列表的求和
闭包Closure
nums_in_global=[15,2,3,9,3.2]#声明一个全局
def foo1(nums_in_function):
print('nums_in_function此时在是foo1中,可以被 访问:',nums_in_function)
def foo2():
return max(nums_in_function)#虽然没有给foo2传入任何参数,但foo2却能访问到foo1中的变量nums_in_function
# return max(nums_in_global)#虽然没有给foo2传入任何参数,但foo2却能访问到全局变量nums_in_global
return foo2 #返回定义函数里面的函数对象
#调用
foo1([5,3,8])()
装饰器
以函数作参数并返回一个替换函数的可执行函数
装饰器的作用就是为已存在的对象添加额外功能
为一个函数增加一个装饰(用另一个函数装饰)
现有如下 三个函数
def foo1():
print ('this is foo1 function')
def foo2():
print ('this is foo2 function')
def foo3():
print ('this is foo3 function')
#现在想为每一个函数都添加一个打印当前时间的功能
#我们可以这样解决
import datetime
def extrafoo(func):
def inner():
print('from inner to execute:',func.__name__) #func.__name__是传入参数的名字
print('the',func.__name__,'result:',func())
print('extra:',datetime.datetime.now())
return inner
@extrafoo #装饰器特性,被装饰的函数定义之后立即运行。
def foo1():
return 'this is foo1 function--'
#@是python装饰器的简便写法,也叫语法糖
#装饰器语法糖在要被包裹的函数前声明。@后面的函数名,是包裹下边函数的函数名extrafoo
#该语法糖省略了
#decorated=foo(test)
#decorated()
# 装饰器在Python使用如此方便都要归因于
# Python的函数能像普通的对象一样能作为参数传递给其他函数
# 可以被赋值给其他变量,可以作为返回值,可以被定义在另外一个函数内。
foo1()