zoukankan      html  css  js  c++  java
  • Python_函数

    函数

    函数的定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,想要执行这个函数,只需调用其函数名即可。

    函数的特性:

    • 减少重复代码;
    • 方便修改,更易扩展;
    • 保持代码的一致性。

    函数名命名规则:

    • 函数名必以下划线或者字母开头,可以包含任意字母、数字或下划线的组合,不能使用任何标点符号;
    • 函数名是区分大小写的;
    • 函数名字不能是保留字。

    语法定义:

    def add(a, b):                                        # 函数名
        print(a + b)
    add(3,7)                                              # 调用函数
                        

    一、函数的参数

    形参与实参:

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

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

    def add(a, b):                                              # a, b 为形参数
        res = a + b
        return res
    c = add(3, 4)                                               # 3, 4 为实参
    print(c)

    函数参数:

    • 必须参数
    • 关键字参数
    • 默认参数
    • 不定长参数

    必须参数:必须参数必须以正确的顺序传入参数,调用时的数据必须和声明时的一样。

    def mu_info(name, age):
        print('Name:%s 
    Age:%d' % (name, age))
    
    mu_info('wj', 24)

    关键字参数:传入参数的时候带上关键字,即使顺序不对,依然可以辨识。

    def mu_info(name, age):
        print('Name:%s 
    Age: %d' % (name, age))
    
    mu_info(age=24, name='wj')

    默认参数:形参定义时就确定好的值调用参数的时候可以省略。

    必选参数在前,默认参数在后,否则Python解释器会报错,

    当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面,变化小的参数可以作为默认参数。

    def mu_info(name, age, sex='male'):
        print('Name:%s 
    Age: %d 
    sex:%s
    ' % (name, age, sex))
    mu_info('wj', 24)
    mu_info('zl', 24)
    mu_info('cf', 25, 'female')

    不定长参数:不定常参数可以处理比当初声明时更多的参数。不定长参数和其他三种参数不同,声明时不会命名。

    *args指的是接受所有无命名参数

    def add(*args):
        sum = 0
        for i in args:
            sum = sum + i
        print(sum)
    
    add(1, 2, 3, 4)

     **kwargs指的是接受键值对的参数保存方式为字典,进行函数内部运算。

    def print_info(**kwargs):
        for i in kwargs:
            print('%s:%s' % (i, kwargs[i]))
    
    print_info(name='mu', age='18', sex='male', job='Linux', height=180)

    不定长参数的位置:*args只能放左边。**kwargs只能放右边不能改变,实参也要按照这个位置顺序来,不然无法保存。

    def print_info(*args, **kwargs):
    # def print_info(**kwargs,*args):                                                       # 错误示范
        for i in args:
            print(i)
        for o in kwargs:
            print('%s:%s' % (o, kwargs[o]))
    
    print_info('mu', 24, sex='male', job='Linux', height=180)
    # print_info(sex='male', 'mu, 24, job='Linux', height=180)                              # 错误示范
    # print_info(sex='male', job='Linux', height=180, 'mu', 24)                             # 错误示范

    不定长参数+默认参数

      如果有默认参数,放左边。

    def print_info(sex='male', *args, **kwargs):
        print(sex)
        print(args)
        print(kwargs)
    
    # print_info()
    print_info('mu', 1, 2, 3, job='Linux')                  # sex 没有打印,因为传入的参数‘mu’占用了sex的位置,所以单独打印了‘mu’,如不是把它打印在元组中

      标准顺序

    def func(name, age=22, *arge, **kwargs)

    二、函数的作用域

    python中的作用域分4种情况
      L: local,局部作用域,即函数中定义的变量;
      E: enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
      G: globa,全局变量就是模块级别的定义的变量;
      B: built-in,系统固定模块里的变量,比如:int,byrearray等。
    搜索变量的优先级顺序依次是:局部作用域 > 外层作用域 > 当前模块中的全局 > python内置作用域, 也就是LEGB。

    局部作用域不能修改全局作用域的变量,如果想要修改,需要用global声明。

    name = "全局作用域"
    def change_name(name):
        print("打印的是那个?:", name)
        name = "局部作用域"
        print("重新赋值后打印的是那个?:" , name)
    
    change_name(name)
    print("全局作用域是否发生改变?:", name)
    name
    = "全局作用域" def change_name(): global name print("打印的是那个?:", name) name = "局部作用域" print("重新赋值后打印的是那个?:" , name) change_name() print("全局作用域是否发生改变?:", name)

    内层局部作用域不能修改外层作用域的变量,如果想要修改,需要用nonlocal声明。

    def change_one():
        name = "外层作用域"
        print(name)
        def change_two():
            name = "局部作用域"
            print(name)
        change_two()
        print(name)
    change_one()
    
    def change_one():
        name = "外层作用域"
        print(name)
        def change_two():
            nonlocal name
            name = "局部作用域"
            print(name)
        change_two()
        print(name)
    change_one()

    小结:

    1. 变量查找顺序: LEGB,局部作用域 > 外层作用域 > 当前模块中的全局 > python内置作用域
    2. 只有模块、类、及函数才能引入新作用域
    3. 对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量
    4. 内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个关键字,就讷讷个完美的实现闭包了。

    三、函数返回值

    想要获取函数的执行结果,可以用return语句将结果返回。

    注意:

      函数里如果没有return,结束时默认会返回一个None;

      return后可以返回多个对象,如果是多个对象,python会帮我们把多个对象封装为一个元组,元组中的元组就是各个对象;

      函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束。

    def f():
        print('ok')
        return
        # return None                                         # 如果不写,python,默认追加这个
    print(f())

     四、高阶函数

    定义:变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

    高阶函数特点:

    •  函数名可以进行赋值;
    • 函数名可以作为函数参数名还可以作为函数的返回值。

    作为函数名:

    def f(n):
        return n * n
    
    def test(a, b, func):
        res = func(a) + func(b)
        return res
    
    print(test(3, 2, f))

    作为函数的返回值:

    def foo():
        def test():
            return 8
        return test                                                     # 其实此时foo() = test
    
    ret = foo()
    print(ret)                                                          # 打印的就是还没有调用的test,也就是test的内存地址,想要调用,再在后边加()就行,打印出来的就是test的值
    print(ret())
    print(foo())
    print(foo()())

     五、递归函数

    递归的特性:

    • 调用自身的函数;
    • 需要有一个明确的结束条件;
    • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少;
    • 递归能处理的,循环都能处理;
    • 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出) 

     递归算阶乘:

    # 正常算阶乘
    def f(n):
        num = 1
        for i in range(n):
            num = (i + 1) * num
        return num
    print(f(5))
    
    
    # 递归引用自己
    def fact(n):
        if n == 1:
            return 1
        return n * fact(n - 1)
    print(fact(5))

     斐波那契数列:

    # 正常算法
    def f(x):
        a, b = 0, 1
        n = 0
        while n <= x:
            # print(b)
            a, b = b, a + b
            n = n + 1
        return b
    print(f(7))
    
    
    # 引用自己
    def fibo(n):
        if n <= 1:
            return n
        return  fibo(n - 1) + fibo(n -2)
    print(fibo(5))

     六、内置函数

    filter:过滤器,需要两个参数。第一个参数是函数,第二个参数是一个序列,只过滤,不修改。

    str = ['a', 'b', 'c', 'd']
    def fun(n):
        if n != 'a':
            return n
    ret = filter(fun, str)                                        # ret是一个迭代器对象
    print(list(ret))

    map:可对列表进行修改

    str = ['a', 'b', 'c', 'd']
    def fun(n):
        return n + 'mu'
    
    ret = map(fun, str)                                           # ret是一个迭代器对象
    print(list(ret))

    reduce:接收参数时,一个函数f,一个列表,传入reduce的函数必须有两个参数,reduce对list中的每次参数反复调用函数f,并返回最终结果

    from functools import reduce
    def f(x, y):
        return x + y
    print(reduce(f, range(1,10)))

    lambda算法:lambda a, b : a + b

    用内置函数算阶乘

    from functools import reduce
    print(reduce(lambda x, y : x * y, range(1,6)))
  • 相关阅读:
    python反射
    numpy笔记
    leetcode43
    leetcode-42
    The Github Flow
    leetcode-37
    leetcode-41
    leetcode-40
    TCP扫盲2
    字节码分析与操作
  • 原文地址:https://www.cnblogs.com/dmjx/p/7903432.html
Copyright © 2011-2022 走看看