python函数参数、参数解构、作用域、递归及匿名函数

一、python函数

  • 由若干语句组成的语句块,函数名称,参数列表构成,它是组织代码的最小单元,通过函数完成一定的功能

1、函数的作用

  •  结构化编程对代码的最基本封装,一般按照功能组织一段代码
  •  封装的目的是为了功能复用,减少冗余代码
  •  使代码更加简洁美观,可读易懂

2、函数的分类

  •  内建函数,如:max(),reversed()等
  •  库函数,如math.ceil()等

3、函数的定义和调用

定义

  • def语句定义函数
  •  函数名就是标识符,命名要求一样
  •  语句块必须缩进,约定4个空格
  •  python的函数若没有return语句,隐式会返回一个None值
  •  定义中的参数列表成为形式参数,只是一种符号表达,简称形参

调用

  •  函数定义只是声明了一个函数,它不会被执行,需要调用
  •  调用方式,就是函数名加上小括号,括号内写参数
  •  调用时写的参数是实际参数,是实实在在的传入的值,简称实参

二、函数参数

  •  参数调用时传入的参数要和定义的个数相匹配(可变参数例外)
  •  位置参数:按照参数定义顺序传入实参fn(1,2)
  •  关键字参数:使用形参的名字来传入实参的方式,如果使用了形参名字,那么传参顺序就可以随意fn(x=1,y=1)
  •  传参:要求位置参数必须在关键字参数之前传入,位置参数是位置对应的;

1、函数参数默认值

  •   参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值
  •   参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用

2、可变参数

  •  在形参前使用*表示该形参是可变参数,可以接收多个实参
  •  收集多个实参为一个tuple元组
    def add(*nums)
        >>> def add(*nums):
        sum = 0
        print(type(nums))
        for x in nums:
            sum += x
        print(sum)
        >>> add(3,6,9)
        <class 'tuple'>
        18

 

3、可变关键字参数

  •  形参前使用**符号,表示可以接收多个关键字参数
  •  收集的实参名称和值组成一个字典
>>> def show(**kwargs):
        for k,v in kwargs.items():
            print('{}={}'.format(k,v))
        >>> show(a=1,b=2,c=3)
        a=1
        c=3
        b=2

4、参数总结

  •  有位置可变参数和关键字可变参数
  •  位置可变参数在形参前使用一个冒号*
  •  关键字可变参数在形参前使用两个冒号**
  •  位置可变参数和关键字可变参数都可以收集若干个实参
  •  混合使用参数的时候,可变参数要放到参数列表的最后,普通参数放在前面
    >>> def fn(x,y,*args,**kwargs):
            print(x)
            print(y)
            print(args)
            print(kwargs)
    
        >>> fn(3,5,6,9,10,a=1,b='python')
        3
        5
        (6, 9, 10)
        {'a': 1, 'b': 'python'}
        >>> fn(3,5)
        3
        5
        ()
        {}
        >>> fn(3,5,a=1,b='python')
        3
        5
        ()
        {'a': 1, 'b': 'python'}
        >>> 


5、keyword-only参数

  •  如果在一个冒号参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通的参数了,
  •  而是keword-only参数
    >>> def fn(*args,x):
            print(x)
            print(args)
    >>> fn(3,5)  调用报错
    >>> fn(3,5,x=7)    
    args已经截获了所有的位置参数,x不使用关键字参数就不可能拿到实参
    
    >>> def fn(*kwargs,x):
            print(x)
            print(args)
    直接报语法错误,因为kwargs会截获所有的关键字参数


6、参数规则

  • 参数列表一般顺序是,普通参数,缺省参数,可变位置参数,keword-only参数,可变关键字参数
>>> def fn(x,y,z=3,*args,m=4,n,**kwargs):
            print(x,y,z,m,n)
            print(args)
            print(kwargs)
            
    def connect(host='localhost', port='3306', user='admin', password='admin', **kwargs):
    
    >>> def connect(host='localhost', port='3306', user='admin', password='admin', **kwargs):
        print(host,port)
        print(user,password)
        print(kwargs)
        >>> connect(db='cmdb')
        localhost 3306
        admin admin
        {'db': 'cmdb'}
        >>> connect(host='192.168.1.1',db='cmdb')
        192.168.1.1 3306
        admin admin
        {'db': 'cmdb'}
        >>> 

 

三、参数解构

  •  给函数提供实参的时候,可以在集合类型前使用*或者**,把集合类型的结构解开,提取所有元素作为函数的实参
  •  非字典类型使用*解构成位置参数
  •  字典类型使用**解构成关键字参数
  •  提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配
举例:
        >>> def add(x,y):
            return x+y
    
        1、位置参数解构
        >>> add(*(4,5))
        9
        >>> add(*[4,5])
        9
        >>> 
        
        2、关键字参数解构
        >>> d = {'x':5,'y':6}
        >>> add(**d)
        11
        >>> 

        3、参数解构和可变参数
        >>> def add(*args):
                result = 0
                for x in args:
                    result += x
                return result

        >>> add(1,2,3)
        6
        >>> add(*[1,2,4])
        7
        >>> add(*range(10))
        45
        >>> 

 

四、函数的返回值和作用域

1、返回值

  • python函数使用return语句返回值,所有函数都有返回值,如果没有return,会隐式调用return None
  •  return语句并不一定是函数的语句最后一条语句
  •  一个函数可以存在多个return语句,但是只有一条可以被执行,如果没有一条return语句被执行到,就执行隐式retnurn
  •  如果有必要,可以显示调用return None,可以简写为return
  •  如果函数执行了return语句,函数就会返回,当前被执行的return语句之后的其他语句不会被执行
  •  return的作用是结束函数调用,返回值不能同时返回多个值

2、作用域

  •  全局作用域:在整个程序运行环境中都可见
  •  局部作用域:在函数,类等内部可见,局部变量使用范围不能超过其所在的局部作用域
举例:
    x = 5
    >>> def foo():
        x += 1
        print(x)
    >>> foo()
    x += 1其实是x = x+1,相当于在foo内部定义一个局部变量x,那么foo内部所有x都是这个局部变量
    但是这个x还没有完成赋值,就被右边拿来使用了,导致报错 
    
    使用全局变量global关键字变量,将foo内的x声明为使用外部的全局作用域中定义的x
    全局作用域中必须要有x的定义
    
    >>> def foo():
            global x
            x = 10
            x += 1 #x在内部作用域为一个外部作用域的变量赋值,所以x += 1不会报错
            print(x)
    >>> foo()

 
3、全局作用域global

  •  外部作用域变量对内部作用域可见,但也不要在这个内部的局部作用域中直接使用;
  •  因为函数的目的就是为了封装,尽量与外界隔离
  •  如果函数需要使用外部全局变量,请使用函数的形参传参解决
  •  一句话:不用global

五、递归函数

  •  函数直接或者间接调用自身就是递归
  •  递归一定要有边界条件,递归前进段,递归返回段
  •  当边界条件不满足的时候,递归前进段
  •  当边界条件不满足的时候,递归返回

1、递归要求

  •  递归一定要有退出条件,递归调用一定要执行到这个退出条件,没有退出条件的递归就是无限调用
  •  递归调用的深度不宜过深,pthon对递归调用的深度做了限制,以保护解释器
斐波那契数列Fibonacci number:1,1,2,3,5,8,13,21,34,55.....
如果设F(n)为该数列的第n项,那么这句话可以写成如下形式:F(n)=F(n-1)+F(n-2)
F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)

pre = 0
cur = 1
print(pre,cur,end='')
n = 4
for i in range(n-1):
    pre,cur = cur,pre+cur
    print(cur,end='')

解析:
fib(3)+fib(2)
fib(3)调用fib(3),fib(2),fib(1)

 

2、递归的性能

  • 斐波那契数列求值性能改进
递归举例:
import datetime

n = 35
start = datetime.datetime.now()

def fib(n):
    return 1 if n<2 else fib(n-1) + fib(n-2)

for i in range(n):
    print(fib(i),end='')
delta = (datetime.datetime.now() - start).total_seconds()
print(delta)


改下后:
pre = 0
cur = 1

print(pre,cur.end='')
def fib(n,pre=0,cur=1):
    pre,cur = cur, pre+cur
    print(cur,end='')
    if n == 2:
        return
    fib(n-1,pre,cur)
fib(n)

3、递归总结

  •  递归是一种很自然的表达,符合逻辑思维
  •  递归相对运行效率低,每一次调用函数都要开辟栈帧
  •  递归有深度限制,如果递归层次太深,函数反复压栈,栈内存很快就溢出
  •  递归可以用循环实现,即使递归代码简洁,能不用递归则不用

 

六、匿名函数

  •  使用lambda关键字来定义匿名函数:lambda 参数列表:表达式:  如lambdax:x**2
  •  参数列表不需要小括号,冒号是用来分割参数列表和表达式的 
  •  不需要使用return,表达式的值就是匿名函数的返回值
  •  lambda表达式只能写在一行,被称为单行函数
  •  主要用途于高阶函数传参时,使用lambda表达式简化代码
举例:
        >>> print((lambda :0)())
        0
        >>> print((lambda x,y=3:x+y)(5))
        8
        >>> print((lambda x,*,y=30:x+y)(5))
        35
        >>> print((lambda x,*,y=30:x+y)(5,y=10))
        15
        >>> print((lambda *args:(x for x in args))(*range(5)))
        <generator object <lambda>.<locals>.<genexpr> at 0x0000000003074258>

 

转载于:https://www.cnblogs.com/jiangzuofenghua/p/11386431.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值