目录
  1. 1. 函数定义
    1. 1.1. 语法
  2. 2. 函数调用
  3. 3. 参数传递
  4. 4. 参数
    1. 4.1. 必需参数
    2. 4.2. 关键字参数
    3. 4.3. 默认参数
    4. 4.4. 不定长参数
      1. 4.4.1. 单星号*(tuple)
      2. 4.4.2. 双星号**(dict)
      3. 4.4.3. 总结
  5. 5. 变量作用域
    1. 5.1. 局部变量
    2. 5.2. 全局变量
    3. 5.3. global关键字
    4. 5.4. 内嵌函数
    5. 5.5. LEGB原则
    6. 5.6. 闭包
    7. 5.7. 装饰器
  6. 6. 函数式编程
    1. 6.1. lambda
    2. 6.2. filter()
    3. 6.3. map()
Python函数

函数定义

以下是简单的规则:

  • 函数代码块以 def关键词 开头,后接 函数标识符名称圆括号()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

语法

1
2
def 函数名(函数列表):
函数体

函数调用

定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

参数传递

在 python 中,类型属于对象,而变量是没有类型的,它只是一个引用,可以代表任何对象

可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。

  • 不可变类型:新建了一个对象赋值给变量,原对象被丢弃
  • 可变类型:修改了对象
  • python的参数传递:
    • 不可变类型:类似于值传递,即拷贝传值,不影响原对象
    • 可变类型:类似于引用传递,影响原对象
  • python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

参数

python中的正式参数类型:

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

必需参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样

关键字参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值

  • 使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值

默认参数

与C++中的默认参数一致,调用函数时,如果没有传递参数,则会使用默认参数。

不定长参数

也称收集参数,你可能需要一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数。

单星号*(tuple)

加了 星号* 的参数会以 元组(tuple) 的形式导入,存放所有未命名的变量参数。

  • 若没有指定,则为空元组
1
2
3
4
5
6
7
8
9
def printinfo(*vartuple, end = "\n"):
"打印所有传入的参数"
for var in vartuple:
print(var, end = end)
return

# 调用printinfo
# printinfo(1,2,3,4,5,end="")
# 12345

双星号**(dict)

加了 两个星号** 的参数会以 字典(dict) 的形式导入。使用方法与上面类似。

总结

  • 星号* 可以单独出现,但是如果单独出现 星号* 后的参数必须用关键字传入。
  • 其实 星号* 起到“打包”作用,将多个参数打包成一个元组
    • 星号* 在形参中的作用是“打包”,在实参中的作用是“解包”
  • 若作为不定长参数传入元组和字典时,要加上星号*双星号**,即传入时要解包,否则元组和字典只会被当作一个参数

变量作用域

局部变量

定义在函数内部的变量是局部变量,它的作用域:函数内部,不能在函数外部被引用

全局变量

与局部变量相对,拥有更大的作用域,可以在函数中访问

  • 函数中可以访问全局变量,但是不能修改(Python会在函数内部新建了一个局部变量,真正的全局变量不被改变)

global关键字

Python使用 屏蔽(shadowing) 保护全局变量:一旦函数内部试图修改全局变量,那么就会新建一个名字一样的局部变量代替,保护全局变量。
如果你还是要坚持修改,使用 global关键字 声明该全局变量,即可在函数内部修改全局变量。

内嵌函数

Python的函数定义支持嵌套,定义在别的函数内部的被称为内嵌函数或者内部函数

  • 内部函数整个作用域在外部函数之内,只有在外部函数里才能调用内嵌函数
  • 内部函数可以引用外部函数的局部变量,此时内部函数称为 闭包 ,但是与全局变量类似,不能在内部函数修改外部函数的局部变量,且不能使用 global 修改,可以使用 nolocal关键字 修改

LEGB原则

变量查找的顺序按照 L→E→G→B

  • LEGB含义解释:
    • L-Local:函数内的名字空间
    • E-Enclosing function locals:嵌套函数中外部函数的名字空间
    • G-Global:函数定义所在模块的名字空间
    • B-Builtin:Python内置模块的名字空间

闭包

闭包(closure)是语法闭包(lexical closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。

  • Python中的闭包表现在:如果一个内部函数里,对在外部作用域但不是在全局作用域的变量进行引用,那么内部函数就是闭包
    • 在闭包中,外部函数的局部变量对应内部函数的局部变量,相当于全局变量与局部变量的关系,可以访问不能修改,但是可以使用 nolocal关键字 修改

装饰器

装饰器(decorator) 的功能:将被装饰的函数当作参数传递给装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数

  • @语法糖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 给eat函数加上日志
    def log(func):
    def wrapper():
    print("开始调用eat函数")
    func()
    print("结束调用eat函数")
    return wrapper

    # @log 等价于 log(eat())
    @log
    def eat():
    print("开始吃了")

    >>> eat()
    开始调用eat函数
    开始吃了
    结束调用eat函数
    • 可以省去手动将eat()传递给log()再将返回值重新赋值的过程(eat = log(eat))
  • 如果使用 @语法糖 时候,eat()有参数,最好使用不定长参数,不然在修改eat()的参数时,也要修改装饰器log()

  • @语法糖也可以嵌套使用

函数式编程

函数式编程(funtional programming),是一种编程范式,它将电脑运算视为函数运算,并避免使用程序状态以及易变对象。

  • 其中,λ演算(lambda calculus) 为该语言最重要的基础。而且,λ演算的函数 可以接受函数当作输入(引数)和输出(传出值)

lambda

Python使用 lambda关键字 来创建 匿名函数,简化函数定义的过程。

  • 基本语法:使用 冒号: 分隔函数的参数及返回值
    • 冒号左边放参数,使用 逗号, 隔开
    • 冒号右边是函数的返回值
  • 执行完 lambda 返回的是一个函数对象,如果要对它进行调用,只需要给它绑定一个临时的名字
    1
    2
    3
    >>> g = lambda x,y : x**y
    >>> g(3,4)
    81

filter()

filter()函数是一个过滤器,它的作用是在海量得数据里面提取出有用得信息

class filter(object)
| filter(function or None, iterable) --> filter object
|
| Return an iterator yielding those items of iterable for which function(item)
| is true. If function is None, return the items that are true.

  • filter有两个参数:第一个是一个函数或者None
    • 如果是一个函数的话,则把第二个可迭代对象里的每一个元素作为函数的参数进行计算,筛选出返回True的元素
    • 如果是None,则直接将第二个参数中为True的值筛选出来
  • filter()返回的是一个迭代器对象
1
2
3
# 筛选出0~9中的奇数
>>> list(filter(lambda x : x%2, range(10)))
[1, 3, 5, 7, 9]

map()

map()会根据提供的函数对指定序列做映射。

class map(object)
| 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.

  • map有两个参数:一个函数和一个可迭代对象,将可迭代对象的每一个元素作为函数的参数进行运算加工,直至可迭代序列每个元素都加工完毕,即 将序列的每一个元素通过函数进行映射
  • map()第二个参数是不定长参数,支持多个可迭代对象。map()会从所有可迭代对象各取一个元素组成元组,类似于zip()函数,然后将元组传递给func(第一个参数)
    • 以短的可迭代对象为止
  • map()返回的是一个迭代器
文章作者: EasonZzZz
文章链接: http://yoursite.com/2020/02/03/学习/Python学习/Python函数/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Nice To Meet U