python函数详解

作者: 凌航 | 来源:发表于2019-05-18 10:20 被阅读20次

    函数定义

    • 格式
    # 格式
    # def 函数名(num):
    #     pass
    # 调用函数:
    # 函数名(num)
    
    • 函数定义实例:
    def caculateNum(num):
        """
        计算1~num质检的累加和
        :param num:累加和的末尾
        :return: 返回累加和
        """
        res = 0
        for i in range(1,num+1):
            res += i
        return res
    
    res = caculateNum(100)
    print(res)
    

    5050

    三种传参方式

    • 按位置顺序传参
    def get_fullname(first_name,last_name='凌宇'):
        full_name = first_name+last_name
        return full_name
    full_name = get_fullname('李','诗才')
    print(full_name)
    

    李诗才

    • 按关键字传参,参数顺序可以任意
    def get_fullname(first_name,last_name='凌宇'):
        full_name = first_name+last_name
        return full_name
    full_name = get_fullname(last_name='诗才',first_name='李')
    print(full_name)
    

    李诗才

    • 默认传参
      当参数缺省时,默认参数会生效,默认参数需要在函数声明时指定其值,如果传参时省略了默认参数,则该参数的值为默认值。如下函数中的last_name
    def get_fullname(first_name,last_name='凌宇'):
        full_name = first_name+last_name
        return full_name
    full_name = get_fullname(first_name='李')
    print(full_name)
    

    李凌宇

    “*”操作符

    将参数放置到一个元组中

    def self_print(name,*a):
        print(name)
        print(type(name))
        print(a)
        print(type(a))
    self_print(1,2,3,4,5,6)
    

    1
    <class 'int'>
    (2, 3, 4, 5, 6)
    <class 'tuple'>

    1被赋值给了name,后面的2,3,4,5,6放置到元组中

    注意:*操作符也可以拆开元组或列表
    效果如下:

    # * 有拆开元组、列表的作用
    t = (1,2,3,4,5)
    print(*t)
    

    1 2 3 4 5

    所以以上代码可以改成如下:

    def self_print(name,*a):
        print(name)
        print(type(name))
        print(a)
        print(type(a))
    self_print(*(1,2,3,4,5,6))
    

    1
    <class 'int'>
    (2, 3, 4, 5, 6)
    <class 'tuple'>

    “**”操作符

    把参数都放入到字典中

    def d_self_print(**kwars):
        print(kwars)
    d_self_print(first_name="li",last_name="shicai")
    

    {'first_name': 'li', 'last_name': 'shicai'}

    注意:“**”操作符如果作用于字典,可以将一个字典拆开所以上面代码可以和下面这种写法等效

    # ** 有拆开字典的作用
    def d_self_print(**kwars):
        print(kwars)
    d_self_print(**{'first_name': 'li', 'last_name': 'shicai'})
    

    {'first_name': 'li', 'last_name': 'shicai'}

    return

    用于返回值,可以用“,”分割,代表一个元组

    def sum_and_avg(*numbers):
        total = sum(numbers)
        avg_number = total/len(numbers)
        return total,avg_number
    sum,avg = sum_and_avg(1,2,3,4,5,6,7,8,9,10)
    print("总和是%f"%(sum))
    print('平均值是%f'%(avg))
    

    总和是55.000000
    平均值是5.500000

    函数的传参问题

    参数分为引用类型,普通类型,python中的基本数据类型都是普通类型。包括数、布尔、字符串型,除了这些之外的都是引用类型。普通类型赋值的时候传的是值;引用类型赋值的时候,传的是址

    l1 = [1,2,3,4,5,]
    l2 = l1
    l2[1] = 5
    print(l1)
    
    a = 5
    b = a
    b = 10
    print(a)
    

    [1, 5, 3, 4, 5]
    5

    上面列表传的是列表的地址,是引用,而b=a的操作是传的值

    传参的本质就是赋值操作,如果传递的引用数据类型,则需要注意是否在函数中对其做出了修改
    为了防止在函数中修改了值,通常会创建一个数据副本

    def power(numbers):
        # 列表推导式可以创建一个副本,不改变原本的值,
        # 函数中的numbers与外部的number不是同一个number,只是值相同,但地址不同
        # numbers = [x**2 for x in numbers]
    
        # 也可以赋值创建副本,不改变原本的值
        # numbers = numbers[:]
        # numbers = list(numbers)
        numbers[3] = 10
        return numbers
    nums = [1,2,3,4,5,6,7,8,9,10]
    print(power(nums))
    print(nums)
    

    函数的本质

    函数的本质其实是地址

    def fun():
        print("hello world!")
    
    # 函数名的本质是函数的地址
    f = fun
    print('f即函数的地址:', f)
    f() # 效果等同于fun()
    

    f即函数的地址: <function fun at 0x000001B512E5C1E0>
    hello world!

    函数的闭包

    即函数的嵌套在函数内部还可以定义一个函数,例子包含在下面变量的讲解中。

    函数变量的作用域

    python中,变量的作用域是以函数为单位的,内层函数可以访问外层函数的变量,但是不能修改

    def outter():
        a = 10
        def inner():
            a = 20
            print('内层',a)
        print('外层未改变',a)
        return inner
    outter()()
    

    外层未改变 10
    内层 20

    • global:加了global表示调用的时全局变量,即最外层变量,而不是当前函数或者外层函数所创建的
    a = 5
    def outter():
        a = 10
        def inner():
            global a # 用了global后,与全局a是同一个,并非副本
            print('内层赋值前',a)
            a = 20
            print('内层赋值后',a)
        inner()
        print('外层函数的变量不变',a)
    outter()
    print('最外层全局变量因内层赋值后而改变',a)
    

    内层赋值前 5
    内层赋值后 20
    外层函数的变量不变 10
    最外层全局变量因内层赋值后而改变 20

    • nolocal
      nolocal修饰变量时,说明使用的嵌套层函数的变量,内层函数访问变量时会先从自己查找,如果找不到,就会层层向上查找
    a = 5
    def outter():
        a = 10
        def inner():
            nonlocal a # 用了global后,与全局a是同一个,并非副本
            print('内层赋值前',a)
            a = 20
            print('内层赋值后',a)
        inner()
        print('外层函数的变量改变',a)
    outter()
    print('最外层全局变量不变',a)
    

    内层赋值前 10
    内层赋值后 20
    外层函数的变量改变 20
    最外层全局变量不变 5

    总结:变量通常只作用于当前函数体内,若内层函数有同名变量,其实只是外层函数变量的副本,改变内层函数变量的值,并不改变外层函数变量的值;但加了global或nolocal关键字修饰后的变量则不同,内层函数变量不再是副本,用global修饰的内层函数变量就是全局变量,nolocal修饰的变量层层向上查找,改变内层函数变量的值即改变的外层的值。类似于传址。

    函数的递归

    所谓递归,就是自己调用自己,编写递归函数时,一定要注意出口的设置,否则函数会无线调用下去;并且可以用递归解决的问题一定可以用循环解决。不多说,直接上个阶乘的例子

    def factorial(n):
        mm = 1
        for num in range(1,n+1):
            mm *=num
        return mm
    
    print(factorial(5))
    def factorial1(n):
        if n== 1:
            return 1
        return n * factorial(n-1)
    print(factorial1(5))
    

    120
    120

    高阶函数

    函数的参数或返回值是函数的函数,一般函数的参数是另一个函数的地址,看下面代码很好理解

    def handle(func, *param):
        return func(*param)
    
    def my_sum(*param):
        sum = 0
        for i in param:
            sum += i
        return  sum
    print(my_sum(1,2,3,4,5,6))
    
    # 函数的参数还是一个函数
    print(handle(my_sum,1,2,3,4,5,6))
    

    21
    21

    可能用到的高级函数

    • map(func, iterator) 该函数会把可迭代对象中的数据一次传递给func函数处理,最后把处理的结果返回
    def power(x):
        return x*x
    result = map(power,[1,2,3,4,5,6])
    print(result)
    print(list(result))
    

    [1, 4, 9, 16, 25, 36]

    • reduce(func,iterator)
      reduce函数累积操作。func函数必须接收两个参数。reduce会把func的运行结果做一个参数,然后从iterator中导入另一个参数,注意,第一次会func会直接从iterator中导入两个参数作为其参数
    from functools import reduce
    li = [1,2,3,4,5]
    result = reduce(lambda x,y:x * y,li)
    print(result)
    

    120

    filter(func,inteable)

    根据func来过滤interable。将interable中的数据传入函数func中如果函数返回True,就保留;否则过滤掉

    li = [1,2,4,5,6,9,10,15]
    result = list(filter(lambda x: x % 2 == 1,li))
    print(result)
    

    [1, 5, 9, 15]

    • .doc
      可以查看函数的文档随便举两个例子就知道他的用法了
    from functools import reduce
    print(reduce.__doc__)
    print(map.__doc__)
    

    reduce(function, sequence[, initial]) -> value
    Apply a function of two arguments cumulatively to the items of a sequence,
    from left to right, so as to reduce the sequence to a single value.
    For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
    ((((1+2)+3)+4)+5). If initial is present, it is placed before the items
    of the sequence in the calculation, and serves as a default when the
    sequence is empty.
    map(func, *iterables) --> map object
    Make an iterator that computes the function using arguments from
    each of the iterables. Stops when the shortest iterable is exhausted.

    相关文章

      网友评论

        本文标题:python函数详解

        本文链接:https://www.haomeiwen.com/subject/ilbzaqtx.html