Python学习总结-函数

本文通过不同的应用场景来总结Python中的函数,具体描述入下:

1.可接受任意数量参数的函数

#示例1  rest是由其他位置参数组成的元组
def avg(first,*rest):
    return (first+sum(rest))/(1+len(rest))
#sample use
avg(1,2)#1.5
avg(1,2,3,4)#2.5
#示例2  所有的位置参数放在args元组中,所有关键字参数放在kwargs字典中

def anyargs(*args,**kwargs):
    print(args)#a tuple
    print(kwargs)#a dict

注意事项:
一个参数只能出现在函数定义中最后一个位置参数后面,*参数只能出现在最后一个参数,在*参数后面仍可以定义其他参数

def a(x,*args,y):
    pass
def b(x,*args,y,**kwargs):
    pass

2.只接受关键字参数的函数

应用场景:希望函数的某些参数强制使用关键字参数传递
解决方案:将强制关键字参数放到某个参数或者当前后面

#示例1
def recv(maxsize,*,block):
    'receive a msg'
    pass

recv(1024,True)#TypeError
recv(1024,block=True)#ok
#示例2  在接受任意多个位置参数的函数中指定关键字参数
def mininum(*values,clip=None):
    m=min(values)
    if clip is not None:
        m=clip if clip > m else m
    return m

mininum(1,5,2,-5,10)#return -5
mininum(1,5,2,-5,10,clip=0)#return 0

3.返回多个值的函数

应用场景:希望构造一个可以返回多个值的函数
解决方案:直接返回一个元组

这里写图片描述

这里写图片描述

4.有默认参数的函数

应用场景:想定义一个函数,它的一个或多个参数是可选的且有一个默认值
解决方案:直接在函数定义中给参数指定一个默认值并放到参数列表的最后一列

#示例1
#带可选参数的函数
def spam(a,b=42):
    print(a,b)

spam(1)#ok a=1,b=42
spam(1,2)#ok a=1,b=2
#示例2  如果默认参数是可修改的容器,如列表、集合或者字典,可使用None作为默认值

def spam1(a,b=None):
    if b is None:
        b=[]
    ...

注意事项:
默认参数的值应该是不可变的对象,如None、True、False、数字或字符串

5.匿名或内联函数

应用场景:如想为sort()操作创建一个简短的回调函数,但是又不想用def定义单行函数,而是希望通过某个快捷方式以内联方式来创建这个函数。
解决方案:使用lambda表达式

#示例1 
#lambda表达式
add=lambda x,y:x+y

add(2,3)# 5
add('hello','world')#helloworld
#示例2 排序或者数据reduce
names=['David','Brian','Raymond','Ned']

sorted(names,key=lambda name:name.split()[-1].lower())
#['Brian', 'David', 'Ned', 'Raymond']

注意事项:
只能定义单个表达式,它的值就是最后的返回值,不能包含其他的语言特性如多个语句、条件表达式、迭代以及异常处理等。

6.带额外状态信息的回调函数

应用场景:当代码中需要依赖回调函数(如事件处理器、等待后台任务完成后的回调等等),且还需要让回调函数拥有额外的状态值以便在其内部使用
解决方案:定义一个需要调用回调函数的函数

#示例1
def apply_async(func,args,*,callback):
    result=func(*args)#计算结果
    callback(result)#请求回调结果
def print_result(result):
    print('Got',result)
def add(x,y):
    return x+y
调用回调函数:
apply_async(add,(2,3),callback=print_result)#5
apply_async(add,('hello','world'),callback=print_result
)#helloworld
示例2  改进回调,上述print_result()只能接受一个参数result。
#现在想让回调函数访问其他变量或者特定环境的变量值
#使用一个绑定方法来代替一个简单函数,如下面新建的
#这个类会保存一个内部序列号,每次接收到一个result序列号加1
class ResultHandler:
          def __init__(self):
    self.sequence=0
          def handler(self,result):
    self.sequence+=1
    print('[{}] Got: {}'.fromat(self.sequence,result))
r=ResultHandler()
apply_async(add,(2,3),callback=r.handler)#5
apply_async(add,('hello','world'),callback=r.handler)#helloworld
#示例3 第二种方式,作为类的替代,使用一个闭包捕获状态值
def make_handler():
    sequence=0
    def handler(result):
        nonlocal sequence
        sequence+=1
        print('[{}] Got: {}'.format(sequence,result))
    return handler

handler=make_handler()
apply_async(add,(2,3),callback=r.handler)#5
apply_async(add,('hello','world'),callback=r.handler)#helloworld
#示例4 第三种方式,使用协程,并使用其send()作为回调方法
def make_handler():
    sequence=0
    while True:
        result=yield
        sequence+=1
    print('[{}] Got: {}'.format(sequence,result))

handler=make_handler()
next(handler)#使用之前需调用该方法
apply_async(add,(2,3),callback=handler.send)#5
apply_async(add,('hello','world'),callback=handler.send)#helloworld

7.访问闭包中定义的变量

应用场景:当想要拓展函数中的某个闭包,允许其能够访问和修改函数的内部变量
解决方案:可以通过访问函数并将其作为函数属性绑定到闭包上来实现

#示例1
def sample():
    n=0
    def func():
        print('n=',n)
    def get_n():
        return n
    def set_n(value):
        nonlocal n
        n=value
    #绑定为函数属性
    func.get_n=get_n
    func.set_n=set_n
    return func
#测试代码:
f=sample()
f()
f.set_n(10)
f()
f.get_n()

注意:
①nonlocal声明可以让我们编写函数来修改内部变量的值
②函数属性允许我们用一种相对简便的方式将访问方法绑定到闭包函数上

#示例2  闭包模拟类的实例 ,将一个内部函数写到一个字典实例中并返回它
import sys
class ClosureInstance:
    def __init__(self,locals=None):
        if locals is None:
            locals=sys._getframe(1).f_locals
        #根据调用标签更新字典实例
        self.__dict__.update((key,value) for key,value in locals.items()                               if callable(value))
    #重定向特殊方法
    def __len__(self):
        return self.__dict__['__len__']()
def Stack():
    items=[]
    def push(item):
        items.append(item)
    def pop():
        return items.pop()
    def __len__():
        return len(items)
    return ClosureInstance()
#测试代码:
s=Stack()
s
s.push(10)
s.push('hello')
len(s)
s.pop()
s.pop()
s.pop()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值