Python 的函数

发布于 2021-06-16 12:35:36 字数 4582 浏览 1508 评论 0

函数的参数

  • 必选参数
  • 默认参数
  • 可变参数

在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是 1 个、2 个到任意个,还可以是 0 个。 这些可变参数在函数调用时自动组装为一个 tuple。

def calc(*numbers):
  sum = 0
  for n in numbers:
    sum = sum + n * n return sum // 结果 calc(1, 2) 5 calc() 0

Python 允许你在 list 或 tuple 前面加一个 * 号,把 list 或 tuple 的元素变成可变参数传进去。

nums = [1, 2, 3]
calc(*nums)
  • 关键字参数

关键字参数允许你传入 0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个 dict。

def person(name, age, **kw):
  print 'name:', name, 'age:', age, 'other:', kw

参数组合

在 Python 中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺 序必须是:必选参数、默认参数、可变参数和关键字参数。

小结

Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。

默认参数一定要用不可变对象,如果是可变对象,运行会有逻辑错误!

要注意定义可变参数和关键字参数的语法:

  • *args 是可变参数,args 接收的是一个 tuple;
  • **kw 是关键字参数,kw 接收的是一个 dict。

以及调用函数时如何传入可变参数和关键字参数的语法:

  • 可变参数既可以直接传入:func(1, 2, 3),又可以先组装 list 或 tuple,再通过 *args 传入:func(*(1, 2, 3));
  • 关键字参数既可以直接传入:func(a=1, b=2),又可以先组装 dict,再通过 **kw 传入:func(**{'a': 1, 'b': 2})。

使用 *args 和 **kw 是 Python 的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。

函数的返回值

1、指定返回值

函数体中 return 语句有指定返回值时返回的就是其值

2、隐含返回值

函数体中没有 return 语句时,函数运行结束会隐含返回一个 None 作为返回值,类型是 NoneType
与 return 、return None 等效,都是返回 None。

3、返回值类型

无论定义的是返回什么类型,return 只能返回单值,但值可以存在多个元素。
return [1,3,5] 是指返回一个列表,是一个列表对象,1,3,5 分别是这个列表的元素
return 1,3,5 看似返回多个值,隐式地被Python封装成了一个元祖返回

注意:

  • return 后续代码不会被执行
  • 只能返回一次,如果要返回多个数据,可先把多个数据包装成一个集合。整体返回(列表、元组、字典.......)

内嵌函数和闭包

内嵌函数

如果在一个函数的内部定义了另一个函数,外部的我们叫他外函数,内部的我们叫他内函数(内嵌函数)。

闭包

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函 数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

#闭包函数的实例
# outer是外部函数 a和b都是外函数的临时变量
def outer( a ):
    b = 10
    # inner是内函数
    def inner():
        #在内函数中 用到了外函数的临时变量
        print(a+b)
    # 外函数的返回值是内函数的引用
    return inner

闭包中内函数修改外函数局部变量

在闭包内函数中,我们可以随意使用外函数绑定来的临时变量,但是如果我们想修改外函数临时变量数值的时候发现出问题了!

在基本的python语法当中,一个函数可以随意读取全局数据,但是要修改全局数据的时候有两种方法:

  1. global 声明全局变量
  2. 全局变量是可变类型数 据的时候可以修改

在闭包内函数也是类似的情况。在内函数中想修改闭包变量(外函数绑定给内函数的局部变量)的时候:

  1. 在python3中,可以用 nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
  2. 在python2中,没有 nonlocal 这个关键字,我们可以把闭包变量改成可变类型数据进行修改,比如列表。

修改闭包变量的实例

# outer是外部函数 a和b都是外函数的临时变量
def outer( a ):
    b = 10  # a和b都是闭包变量
    c = [a] #这里对应修改闭包变量的方法2
    # inner是内函数
    def inner():
        #内函数中想修改闭包变量
        # 方法1 nonlocal关键字声明
        nonlocal  b
        b+=1
        # 方法二,把闭包变量修改成可变数据类型 比如列表
        c[0] += 1
        print(c[0])
        print(b)
    # 外函数的返回值是内函数的引用
    return inner

还有一点需要注意:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量 实际上只有一份,每次开启内函数都在使用同一份闭包变量

#coding:utf8
def outer(x):
    def inner(y):
        nonlocal x
        x+=y
        return x
    return inner
a = outer(10)
print(a(1)) //11
print(a(3)) //14

两次分别打印出 11 和 14,由此可见,每次调用 inner 的时候,使用的闭包变量 x 实际上是同一个。

闭包有啥用

1、装饰器!装饰器是做什么的??其中一个应用就是,我们工作中写了一个登录功能,我们想统计这个功能执行花了多长时间,我们可以用装饰器装饰这 个登录模块,装饰器帮我们完成登录函数执行之前和之后取时间。

2、面向对象!经历了上面的分析,我们发现外函数的临时变量送给了内函数。大家回想一下类对象的情况,对象有好多类似的属性和方法,所以我们创建类,用类创建出来的对象都具有相同的属性方法。闭包也是实现面向对象的方法之一。在 python 当中虽然我们不这样用,在其他编程语言入比如 JavaScript 中,经常用闭包来实现面向对象编程

3、实现单利模式! 其实这也是装饰器的应用。单利模式毕竟比较高大,,需要有一定项目经验才能理解单利模式到底是干啥用的,我们就不探讨了。

匿名函数

python 使用 lambda 来创建匿名函数。 匿名函数有个限制,就是只能有一个表达式,不用写 return,返回值就是该表达式的结果。

>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25, 36, 49, 64, 81]

通过对比可以看出,匿名函数 lambda x: x * x 实际上就是:

def f(x):
    return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

lambda 这个名称来自于 LISP,而 LISP 则是从 lambda calculus(一种符号逻辑形式)取这个名称的。 在 Python 中,lambda 作为一个关键字,作为引入表达式的语法。想比较 def 函数,lambda 是单一的表达式,而不是语句块。

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

1、lambda 只是一个表达式,函数体比 def 简单很多。
2、lambda 的主体是一个表达式,而不是一个代码块。仅仅能在 lambda 表达式中封装有限的逻辑进去。
3、lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
4、虽然 lambda 函数看起来只能写一行,却不等同于 C 或 C++ 的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

匿名函数的优点

1、使用 Python 写一些脚本时,使用 lambda 可以省去定义函数的过程,让代码更加精简。
2、对于一些抽象的,不会被别的地方再重复使用的函数,有时候函数起个名字也是个难题,使用 lambda 不需要考虑命名的问题
3、使用 lambda 在某些时候然后代码更容易理解

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

文章
评论
84965 人气
更多

推荐作者

转角预定愛

文章 0 评论 0

玩物

文章 0 评论 0

qq_dEbOhs

文章 0 评论 0

陆九渊

文章 0 评论 0

qq_ScZtKg

文章 0 评论 0

权谋诡计

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文