零基础入门学Python(六)—— 函数(上)

零基础入门学Python系列内容的学习目录                                 →                            \rightarrow                 →零基础入门学Python系列内容汇总


函数(上)


  需要学习的基础知识有:函数、参数、闭包、lambda表达式、递归等。因本部分内容较多,故分为上下两个篇章。
    1、2、3部分内容见零基础入门学Python(六)—— 函数(上)
    4、5、6、7部分内容见零基础入门学Python(六)—— 函数(下)

1. Python的乐高积木

  为了使得程序的代码更为简单,就需要把程序分解成较小的组成部分,有三种方法可以实现:函数、对象和模块。

1.1 创建和调用函数

  我们之前使用的BIF就是Python帮我们封装好的函数,用的时候很方便,根本不需要去想实现的原理。一个程序可以按照不同功能的实现分割成许许多多的代码块,每一个代码块就可以封装成一个函数。
  在Python中创建一个函数用def关键字:

  example1: >>>def myFirstFunction():
             print(“这是我创建的第一个函数!”)

  要注意的是,在函数名后要加上一对小括号。这对括号是必不可少的,因为有时候需要在里面放点东西。
  在Python中调用一个函数,就是直接写出函数名加上小括号即可:

  example2: >>>myFirstFunction()
       这是我创建的第一个函数!

  函数的调用机制和运行机制:当函数myFirstFunction()发生调用操作的时候,Python会自动往上找到def myFirstFunction()的定义过程,然后依次执行该函数所包含的代码块部分。只需要一条语句,就可以轻松实现函数内的所有功能。
  假如要把刚才的内容打印三次,只需要调用三次函数即可:

  example3: >>>for i in range(3):
            myFirstFunction()
        这是我创建的第一个函数!
        这是我创建的第一个函数!
        这是我创建的第一个函数!

1.2 函数的参数

  之前在函数名后加的一对小括号里面放的东西就是函数的参数,参数会使得函数可以实现个性化。

  example1: >>>def mySecondFunction(name):
             print(name + “,你好!”)

        >>>mySecondFunction(“小明”)
        小明,你好!
        >>>mySecondFunction(“张三”)
        张三,你好!

  如果需要使用多个参数的话,只需要用逗号隔开即可:

  example2: >>>def add(num1, num2):
             print(num1 + num2)

        >>>add(1, 2)
        3

1.3 函数的返回值

  有时候需要函数为我们返回一些数据来报告执行的结果,所以函数需要返回值。在函数中使用关键字return,后面跟着的就是指定要返回的值:

  example1: >>>def add(num1, num2):
             return num1 + num2

        >>>add(1, 2)
        3

2. 灵活即强大

2.1 形参和实参

  参数从调用的角度来说,分为形式参数(parameter)和实际参数(argument)。形参是指函数创建和定义过程中小括号里的参数,而实参则是指函数在被调用的过程中传递进来的参数。

  example1: >>>def myFirstFunction(name):
             print(name)

        >>>myFirstFunction(“小明”)
        小明

其中,myFirstFunction(name)name是形参,因为它只代表一个位置、一个变量名;而调用myFirstFunction("小明")传递的"小明"是实参,因为它是一个具体的内容,是赋值到变量名中的值。

2.2 函数文档

  函数文档的作用是描述该函数的功能。

   example1: >>>def exchangeRate(dollar):
             " " "美元 -> 人民币
             汇率暂定为6.5
             " " "
             return dollar * 6.5

        >>>exchangeRate(10)
        65.0

  在函数开头写下的字符串是不会打印出来的,但它会作为函数的一部分存储起来。这个称为函数文档字符串,它的功能跟注释是一样的。不一样的是函数的文档字符串可以通过特殊属性_ _doc_ _获取:

  example2: >>>exchangeRate._ _ doc _ _
        ’ 美元 -> 人民币 \n\t 汇率暂定为6.5 \n\t ’

  另外,当我们想用一个函数但却不确定其用法的时候,可以通过help()函数来查看函数的文档。

  example3: >>>help(exchangeRate)
        Help on function exchangeRate in module _ _ main _ _ :

        exchangeRate(dollar)
          美元 -> 人民币
          汇率暂定为6.5

2.3 关键字参数

  普通的参数叫位置参数,通常在调用一个函数的时候,我们可能会把位置参数的顺序弄乱以至于函数无法按照预期实现,因此就有了关键字参数,可以简单地解决这个潜在的问题。

  example1: >>>def saySomething(name, words):
             print(name + ’ -> ’ + words)

        >>>saySomething(“小明”, “你好!”)
        小明 -> 你好!
        >>>saySomething(“你好!”, “小明”)
        你好! -> 小明
        >>>saySomething(words = “你好!”, name = “小明”)
        小明 -> 你好!

  关键字参数其实就是在传入实参时指定形参的变量名。

2.4 默认参数

  默认参数是在定义的时候赋予了默认值的参数:

  example1: >>>def saySomething(name = “小明”, words = “你好!”):
             print(name + ’ -> ’ + words)

        >>>saySomething( )
        小明 -> 你好!
        >>>saySomething(“张三”, “再见!”)
        张三 -> 再见!
        >>>saySomething(words = “好久不见!”, name = “李四”)
        李四 -> 好久不见!

  使用默认参数的话,就可以不带参数去调用函数。默认参数和关键字参数的区别为:

  • 关键字参数是在函数调用的时候通过参数名指定要赋值的参数,这样做就不怕因为搞不清参数的顺序而导致参数调用出错。
  • 默认参数是在参数定义过程中为形参赋值,当函数调用的时候不传递实参,则默认使用形参的初始值代替。

2.5 收集参数

  收集参数大多时候也被称为可变参数,编写程序时,有时候程序员也不知道这个函数到底需要多少个参数,这时候仅需要在参数前面加上星号( * )即可:

  example1: >>>def test( * params):
             print(“有 %d 个参数” % len(params))

        >>>test( ‘H’, ‘e’, ‘l’, ‘l’, ‘o’)
        有 5 个参数
        >>>test( ‘小明’, ‘e’, 123)
        有 3 个参数

  如果在收集参数后边还需要指定其他参数,在调用函数的时候就应该使用关键字参数来指定,否则Pyhton就会把实参列入收集参数的范畴。

  example2: >>>def test( * params, extra):
             print(“收集参数是:”, params)
             print(“位置参数是:”, extra)

        >>>test(1, 2, 3, 4, 5)
        Traceback (most recent call last):
         File “

  Pyhton就是把标志为收集参数的参数们打包成一个元组。如果编程时参数中带有收集参数,那么建议将其他参数设置为默认参数,这样不容易出错。

  example3: >>>def test( * params, extra = “8”):
             print(“收集参数是:”, params)
             print(“位置参数是:”, extra)

        >>>test(1, 2, 3, 4, 5)
        收集参数是: (1, 2, 3, 4)
        位置参数是: 5

  星号( * )其实既可以打包又可以“解包”。假如我们需要将一个列表a传入test函数的收集参数 * params中,那么调用test(a)时便会出错,此时需要在a前边加上个星号( * )表示实参需要“解包”后才能使用:

  example4: >>>def test( * params):
             print(“有 %d 个参数” % len(params))
             print(“第二个参数是” , params[1])

        >>>a = [1, 2, 3, 4, 5]
        >>>test(a)
        有 1 个参数
        Traceback (most recent call last):
         File “

  Python还有另一种收集方式,就是用两个星号( ** )表示,两个星号的收集参数表示将参数们打包成字典的形式。

3. 我的地盘听我的

3.1 函数和过程

  函数(function)是有返回值的,而过程(procedure)是简单、特殊并且没有返回值的。Pyhton严格来说只有函数,没有过程!

  example1: >>>def hello( ):
             print(“Hello~”)

        >>>print(hello( ))
        Hello~
        None

  通过上面例子可以发现,调用print(hello( ))之后打印了两行文字。当不写return语句的时候,Pyhton会默认函数是return None的,所以说Pyhton所有的函数都有返回值。

3.2 再谈谈返回值

  在许多编程语言中,我们说一个函数是整型,其实就是指这个函数会返回一个整型的返回值。而Pyhton不同,Pyhton可以动态确定函数的类型,而且函数还能返回不同类型的值。另外,Pyhton似乎还可以同时返回多个值:

  example1: >>>def test( ):
             return[1, ‘小明’, ‘abc’]

        >>>test( )
        [1, ‘小明’, ‘abc’]

  Pyhton可以利用列表打包多种类型的值一次性返回,也可以直接用元组的形式返回多个值:

  example2: >>>def test( ):
             return 1, ‘小明’, ‘abc’

        >>>test( )
        (1, ‘小明’, ‘abc’)

3.3 函数变量的作用域

  变量的作用域就是平时所说的变量可见性,一般的编程语言都有局部变量(Local Variable)和全局变量(Global Variable)之分。看一个例子:

def discounts(price, rate):
    final_price = price * rate    return final_price

old_price = float(input('请输入原价:'))rate = float(input('请输入折扣率:'))new_price = discounts(old_price, rate)print('打折后价格是:', new_price)

请输入原价:10
请输入折扣率:0.7
打折后价格是: 7.0

  在函数discounts()中,两个参数是pricerate,还有一个是final_price,它们都是discounts()函数中的局部变量。如果将代码修改如下:

def discounts(price, rate):
    final_price = price * rate    return final_price

old_price = float(input('请输入原价:'))rate = float(input('请输入折扣率:'))new_price = discounts(old_price, rate)print('打折后价格是:', new_price)print('这里试图打印局部变量final_price的值:', final_price)

请输入原价:10
请输入折扣率:0.7
打折后价格是: 7.0
Traceback (most recent call last):
 File “C:\Users\Administrator\Desktop\1.py”, line 9, in < module >
  print(‘这里试图打印局部变量final_price的值:’, final_price)
NameError: name ‘final_price’ is not defined

  运行之后就会报错,错误原因为final_price没有被定义过,Python找不到final_price这个变量。这是因为final_price只是一个局部变量,它的作用范围之在它的地盘上——discounts()函数的定义范围内有效。
  总结一下:在函数里边定义的参数以及变量,都称为局部变量,出了这个函数,这些变量都是无效的。Python在运行函数的时候,利用(Stack)进行存储,当执行完该函数后,函数中的所有数据都会被自动删除,所以在函数外边是无法访问到函数内部的局部变量的。
  与局部变量相对的是全局变量,上述程序中old_pricenew_pricerate 都是在函数外边定义的,它们都是全局变量,全局变量拥有更大的作用城。例如在函数中可以访问到它们:

def discounts(price, rate):
    final_price = price * rate    print('这里试图打印全局变量old_price的值:', old_price)
    return final_price

old_price = float(input('请输入原价:'))rate = float(input('请输入折扣率:'))new_price = discounts(old_price, rate)print('打折后价格是:', new_price)

请输入原价:10
请输入折扣率:0.7
这里试图打印全局变量old_price的值:10.0
打折后价格是: 7.0

  在Pyhton中,我们可以肆无忌惮的访问一个全局变量,但当试图修改它时就需要小心了。看如下所示代码:

def discounts(price, rate):
    final_price = price * rate
    old_price = 20
    print('在全局变量中修改后old_price的值:', old_price)
    return final_price

old_price = float(input('请输入原价:'))rate = float(input('请输入折扣率:'))new_price = discounts(old_price, rate)print('全局变量old_price现在的值是:', old_price)print('打折后价格是:', new_price)

请输入原价:10
请输入折扣率:0.7
在全局变量中修改后old_price的值: 20
全局变量old_price现在的值是: 10.0
打折后价格是: 7.0

  如果在函数内部试图修改全局变量,那么Python会创建一个新的局部变量替代(名字跟全局变量相同),但真正的全局变量是纹丝不动的。
  关于全局变量,我们也来总结一下:全局变量在整个代码段中都是可以访问到的,但是不要试图在函数内部去修改全局变量的值,因为那样Python会自动在函数内部新建一样的局部变量代替。如果想在函数里边去修改全局变量的值,可以在函数里边嵌套定义一个新的函数。

  后半部分内容见零基础入门学Python(六)—— 函数(下)

4. 内嵌函数和闭包

5. lambda表达式

6. 递归

7. 介绍两个BIF:filter()和map()

上一篇:知乎热榜爬取


下一篇:Grafana导入node_exporter图标后,显示Panel plugin not found:table-old