zoukankan      html  css  js  c++  java
  • python 函数(一)

    预习:

      一  函数的返回值可以以元组的形式返回多个。

      补充一个小知识: 

      判断是否为元组的核心是逗号,即便是没有()包裹起来,它也是元组。明白这一点,就会有恍然大悟的感觉。

      例如: 

    a=1,2
    print(a,type(a))
    

      输出:

    (1, 2) <class 'tuple'>

      

      所以,下面就比较容易理解了:

    def plus(x,y):
        return x,x+y                 #看起来是两个返回值,本质上是一个元组,因为有个逗号,所有python会认为x,x+y 就是元组(x,x+y)。下面的结果就是理所当然
    print(plus(1,2))
    

      等价于:

    def plus(x,y):
        a=x,x+y                      #在这里,a就是一个元组。
        return a
    print(plus(1,2))

      输出:

    (1, 3)
    

      二  函数传参的时候注意可变类型与不可变类型。

      函数定义阶段读取的时候,函数变量会被一同读取。默认参数的值在定义阶段就确定了。函数体不被读取。

      传参的时候,一定要区分可变类型与不可变类型。两者会有本质的区别。  

      传的参数是不可变类型时:

    name='hello'
    def func(x):
        return x.replace('l','g')
    result=func(name) print(result) print(name)

      输出:

    heggo
    hello
    

      会发现,传入的变量本身并没有变化。

      传的参数是可变类型时:

    l=[1,2,3,4]
    def func(x):
        x.append(5)
        return x
    result=func(l)
    print(result)
    print(l)

      输出:

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

      去上面不可变类型不同的是,可变类型作为参数传入的时候,会被函数所影响,会发生变化。

      原因就在于,传参实际上是有这样一个过程。参数传进来的时候,会有一个赋值的过程。

    name='hello'
    def func(x):
        return x.replace('l','g')
    result=func(name)
    # name='hello'
    # x=name
    # x='hello'              #x,name在这个时候尽管都等于‘hello’,指向‘hello’在内存中的同一个地址。但是因为是不可变类型,所哟x.repalce()之后,x就会指向一个新的内存地址,表现出来x发生了变化。而name本身没有变化
    print(result)
    print(name)
    

      

    l=[1,2,3,4]
    def func(x):
        x.append(5)
        return x
    result=func(l)
        # l=[1,2,3,4]      #x=l,实际上变量名x,变量名l,指向内存中同一个空间。列表是可变类型,对其的方法都会使其本身发生变化。
        # x=l
        # x=[1,2,3,4]
    print(result)
    print(l)
    

      

      三 关于 *与**

      作用:

      *与**在函数定义阶段(形参)起收集的作用,在函数调用阶段(实参)是打散分配的作用。*针对列或者元组格式,**针对是字典格式。

      *与**在形参位置:

    def func(*args):
        print(args)
    func(1,2,3,4)
    
    def func(**kwargs):
        print(kwargs)
    func(x=1,y=2)
    

      输出:

    (1, 2, 3, 4)
    {'x': 1, 'y': 2}
    

      

      *与**在形参位置  实参位置:

    def func(*args):
        print(args)
    a=(1,2,3,4)
    func(*a)
    
    d=dict(x=1,y=2)
    def func(**kwargs):
        print(kwargs)
    func(**d)
    

      输出:

    (1, 2, 3, 4)
    {'x': 1, 'y': 2}
    

      

      什么时候用呢,请看下面示例:

    msg=dict(name='egon',age=88)                                                               #msg数据类型是字典
    def func(**kwargs):                                                                        # 函数定义阶段(形参)
        print('{}老师已经{}岁了'.format(kwargs['name'],kwargs['age']))                           
    func(**msg)                                                                                #函数调用阶段(实参)
    
    
    def fun(kwargs):
        print('{}老师已经{}岁了'.format(kwargs['name'], kwargs['age']))                          #传的参数数据类型是字典是可以的
    fun(msg)
    

      输出:

    egon老师已经88岁了
    egon老师已经88岁了
    

      func()定义和调用阶段都使用了*,fun()函数两处都没有用到,但得到了同样的效果。所以型号只在定义函数(允许使用不定数目的参数)或者调用(分割字典或者序列)时才有用。

      

      四 作用域(命名空间):namespace

      每个函数调用都会创建一个新的作用域。

      python的函数是可以嵌套的,也就是可以将一个函数放在另一个函数内部。

      举个例子:

    def func1():
        def func2():
            print('hello world')
        func2()
    func1()
    

      输出:

    hello world
    

      

        由函数是可以嵌套的,可以引出一个很重要的概念——闭包函数。简单的来说,闭包函数是由两层函数构成,调用外层函数返回内层函数的地址,此时的内层函数并没有被调用。 之后再对内层函数传参加括号调用时,重点到了,内层函数除了自己本身的作用域可以访问,还可以访问它的定义所在的作用域。换句话说,内层函数是带着定义它的环境和(相关的自己局部变量)。

      函数存储子封闭作用域的行为叫做闭包。

      闭包函数是针对内层函数而说的,内层函数先天是是带着外层函数的作用域和它自己本身的作用域。

    def func1(x):
        def func2(y):
            return x+y
        return func2
    var=func1(2)
    res=var(3)
    print(res)
    

      输出:5

      

      想当然的直接调用func2,是会出现这种情况。

    def func1(x):
        def func2(y):
            return x+y
        return func2
    res=func2(3)           #这一行报错,因为向上找找不到func2这个函数,找不到定义它的语句。报错。
    print(res)
    

      

      五 函数式编程

      把函数作为参数传入,这样的函数就称为高阶函数。而函数式编程就是指这种高度抽象的编程范式。

      在python2 与 python3 中会有不同:

      map():映射。

      在python2中:

    >>> map(lambda x:x**2,[1,2,3,4,5])
    [1, 4, 9, 16, 25]
    

      在python3中:

    >>> map(lambda x:x**2,[1,2,3,4,5])
    <map object at 0x000001D455A48A90>
    >>> list(map(lambda x:x**2,[1,2,3,4,5]))
    [1, 4, 9, 16, 25]
    

      

      filte():过滤

      在python2中:

    >>> map(lambda x:x**2,[1,2,3,4,5])
    [1, 4, 9, 16, 25]
    

     

      在python3中

    >>> filter(lambda x:x%2==1,[1,2,3,4,5])
    <filter object at 0x000001D455A48A58>
    >>> list(filter(lambda x:x%2==1,[1,2,3,4,5]))
    [1, 3, 5]
    

      reduce()

      在python2中:

    >>> reduce(lambda x,y:x*y,[1,2,3,4])
    24
    

      在Python3中:

    >>> reduce(lambda x,y:x*y,[1,2,3,4])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'reduce' is not defined
    

      原因是讲reduce函数放在了functools 模块了,需要导入。

    >>> from functools import reduce
    >>> reduce(lambda x,y:x*y,[1,2,3,4])
    24
    

      

      使用reduce可以实现这样一个功能。

      将[1,2,3,4,5,6,7,8]变成 12345678,列表内是整型,所以不能用join方法。

    >>> reduce(lambda x,y:10*x+y,[1,2,3,4,5,6,7,8])
    12345678
    

      完美!

      六 列表推导式

      可能和filter函数能实现一样的效果。  

    >>> list(filter(lambda x:x%2==0,[1,2,3,4,5,6,7,8]))
    [2, 4, 6, 8]
    >>> seq=[1,2,3,4,5,6,7,8]
    >>> [x for x in seq if x%2==0]
    [2, 4, 6, 8]
    

      

  • 相关阅读:
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    5.14
    5.13
    5.12
  • 原文地址:https://www.cnblogs.com/654321cc/p/7440273.html
Copyright © 2011-2022 走看看