python学习笔记3 函数 生成器 闭包 装饰器

函数

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值