天天看点

疯狂Python讲义学习笔记(含习题)之 函数和lambda表达式一、函数入门二、函数的参数三、局部函数四、函数的高级内容五、局部函数与lambda表达式

函数是执行特定任务的一段代码,程序通过将一段代码定义成函数,并为该函数指定一个函数名,这样即可在需要的时候多次调用这段代码。

一、函数入门

通俗来讲,所谓函数,就是指为一段实现特定功能的代码“取”一个名字,以后即可通过该名字来执行(调用)该函数。

函数可以接收零个或多个参数,也可以返回零个或多个值。

疯狂Python讲义学习笔记(含习题)之 函数和lambda表达式一、函数入门二、函数的参数三、局部函数四、函数的高级内容五、局部函数与lambda表达式

从函数定义者(实现函数的人)的角度来看,至少需要想清楚一下3点:

● 函数需要几个关键的需要动态变化的数据,这些数据应该被定义成函数的参数。

● 函数需要传出几个重要的数据(就是调用该函数的人希望得到的数据),这些数据应该被定义成返回值。

● 函数的内部实现过程。

函数定义语法格式:

def 函数名(形参列表):
    # 由零条到多条可执行语句组成的函数
    [return [返回值]]
           

● 函数名:一个合法的标识符。

● 形参列表:用于定义该函数可以接受的参数。由多个形参名组成,之间用英文逗号隔开。——谁调用,谁负责对形参赋值。

在函数体中使用return语句可以显式地返回一个值,return语句返回的值既可是有值的变量,也可是一个表达式。

通过内置的help()函数可以查看函数的帮助文档——只要把一段字符串放在函数声明之后、函数体之前,这段字符串将被作为函数的部分,这个文档就是函数的说明文档。

除了help()函数,也可通过__doc__属性访问函数的说明文档。

在一个函数体内调用它自身,被成为函数递归。函数递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。

如:已知有一个数列:f(0) = 1, f(1) = 4, f(n+2) = 2*f(n+1) + f(n),其中n是大于0的整数,求f(10)的值。

def fn(n):
    if n == 0:
        return 1
    elif n == 1:
        return 4
    else:
        # 在函数体中调用它自身,就是函数递归
        return 2 * fn(n - 1) + fn(n - 2)
​
​
# 输出fn(10)的结果
print("fn(10)的结果是:", fn(10))
           

※ 递归一定要向已知方向进行。

二、函数的参数

按照形参位置传入的参数被称为位置参数。根据参数名来传入参数值被称为关键字(keyword)参数。

使用位置参数的方式来传入参数值,必须严格按照定义函数时指定的顺序来传入参数值,使用关键字参数调用时,可交换参数的位置。

如果混合使用了关键字参数和位置参数,则关键字参数必须位于位置参数之后。换句话说,关键字参数之后只能是关键字参数。

Python要求将带默认值的参数定义在形参列表的最后。

Python允许在形参前面添加一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入。

Python允许个数可变的形参处于形参列表的任意位置(不要求是形参列表的最后一个参数),但一个函数最多只能带一个支持“普通”参数收集的形参。

Python还可以收集关键字参数,此时Python会将这种关键字参数收集成字典。为了让Python能收集关键字参数,需要在参数前面添加两个星号。

所谓逆向参数收集,指的是在程序已有列表、元组、字典等对象的前提下,把它们的元素“拆开”后传给函数的参数。逆向参数收集需要在传入的列表、元组参数之前添加一个星号,在字典参数之前添加两个星号。代码如下:

def test(name, message):
    print("用户是:", name)
    print("欢迎消息:", message)
​
​
my_list = ['刘德华', '欢迎来Python世界']
test(*my_list)
           

即使支持收集的参数,如果需要将一个元组传给该参数,那么同样需要使用逆向收集。如:

def foo(name, *nums):
    print("name参数:", name)
    print("nums参数:", nums)
​
​
my_tuple = (1, 2, 3)
# 使用逆向收集,将my_tuple元组的元素传给nums
foo('fkit', *my_tuple)
           

这里的*号相当于解包操作符,它会将元组拆分成元素,然后依次赋值给函数的形参。如果通过

foo(*my_tuple)
           

来调用,则会将1赋值给name,2,3赋值给nums。

如果不使用逆向收集,通过foo(my_tuple)则会将my_tuple整体作为参数值传给name参数。

字典也支持逆向收集,以关键字参数的形式传入函数。

Python中函数的参数传递机制都是“值传递”。就是将实际参数值的副本(复制品)传入函数,而参数本身不会受到影响。

● 不管什么类型的参数,在Python函数中对参数直接使用“=”符号赋值是没用的,直接使用“=”符号赋值并不能改变参数。

● 如果需要让函数修改某些数据,则可以通过把这些数据包装成列表、字典等可变对象,然后把列表、字典等可变对象作为参数传入函数,在函数中通过列表、字典的方法修改它们。

变量分两种:

● 局部变量。在函数中定义的变量,包括参数,都被称为局部变量。

● 全局变量。在函数外面、全局范围内定义的变量,被称为全局变量。

每个函数执行时,系统都会为该函数分配一块“临时内存空间”,所有的局部变量都被保存在这块临时内存空间内,当函数执行完毕,这块内存空间就被释放了,局部变量也就失效了,因此离开函数之后就不能再访问局部变量了。

全局变量可以在所有函数内被访问。

Python提供了三个工具函数来获取指定范围内的“变量字典”

● globals():该函数返回全局范围内所有变量组成的“变量字典”

● locals():该函数返回当前局部范围内所有变量组成的“变量字典”

● vars(object):获取在指定对象范围内所有变量组成的“变量字典”。如果不传入object参数,vars()和locals()的作用完全相同。

● locals()总是获取当前局部范围内所有变量组成的“变量字典”,如果在全局范围内(在函数之外)调用locals()函数,同样会获取全局范围内所有变量组成的“变量字典”;而globals()无论在哪里执行,总是获取全局范围内所有变量组成的“变量字典”

● 使用locals()和globals()获取的“变量字典”只应被访问,不应被修改。

Python语法规定:在函数内部对不存在的变量赋值时,默认就是重新定义新的局部变量。

可以通过globals()函数在函数内部定义全局变量。

为了避免在函数中对全局变量赋值(不是重新定义局部变量),可以使用global语句来声明全局变量。

三、局部函数

Python支持在函数体内定义函数,被成为局部函数。

Python提供了nonlocal关键字,可以声明访问赋值语句只是访问该函数所在的函数内部的局部变量。

global用于声明访问全局变量,而nonlocal用于声明访问当前函数所在函数内的局部变量。

四、函数的高级内容

Python的函数也是一种值:所有函数都是function对象,这意味着可以把函数本身赋值给变量,就像把整数、浮点数、列表、元组赋值给变量一样。

Python支持像使用其他参数一样使用函数参数。

Python还支持使用函数作为其他函数的返回值。

五、局部函数与lambda表达式

lambda表达式是现代编程语言争相引入的一种语法,如果说函数是命名的、方便复用的代码块,那么lambda表达式则是功能更灵活的代码块,它可以在程序中被传递和调用。

Python要求lambda表达式只能是单行表达式。

lambda表达式的语法格式如下:

lambda [parameter_list]: 表达式
           

● lambda表达式必须使用lambda关键字定义

● 在lambda关键字之后、冒号左边的是参数列表,可以没有参数,也可以有多个参数。如果有多个参数,则需要用逗号隔开,冒号右边是该lambda表达式的返回值。

lambda表达式的本质就是匿名的、单行函数体的函数。

lambda表达式的用途:

● 对于单行函数,使用lambda表达式可以省去定义函数的过程,让代码更简洁。

● 对于不需要多次复用的函数,使用lambda表达式可以在用完之后立即释放,提高了性能。

习题:

1. 定义一个函数,该函数可接收一个list 作为参数,该函数使用直接选择排序对list 排序。

def sort_list(sort_list):
    temp_list = []
    for i in range(len(sort_list)):
        min_var = min(sort_list)
        sort_list.remove(min_var)
        temp_list.append(min_var)
    return temp_list
​
​
my_list = [3, 2, 3, 2, 1, 3, 2, 2, 1]
print(sort_list(my_list))
           

2. 定义一个函数,该函数可接收一个list 作为参数,该函数使用冒泡排序对list 排序。

def sort_list(sort_lst):
    lst_len = len(sort_lst)
    for i in range(0, lst_len):
        sort_flag = True
        for j in range(0,lst_len - i - 1):
            if sort_lst[j] > sort_lst[j + 1]:
                sort_lst[j], sort_lst[j + 1] = sort_lst[j + 1], sort_lst[j]
                sort_flag = False
        if sort_flag:
            break
    return sort_lst
​
​
my_lst = [5, 9, 3, 1, 2, 8, 4, 7, 6]
print(sort_list(my_lst))
           

3. 定义一个is_leap(year) 函数,该函数可判断year是否为闰年。若是闰年,则返回True ;否则返回False 。

def is_leap(year):
    year = int(year)
    if(year % 4 == 0) and (year % 100 != 0):
        return True
    elif (year % 400 == 0):
        return True
​
    else:
        return False
​
​
while(True):
    year = input('请输入一个年份:')
    if year == 'exit':
        import sys
        sys.exit(0)
    print('%s是闰年吗?%s' % (year, is_leap(year)))
           

4. 定义一个count_str_ char( my_ str)函数,该函数返回参数字符串中包含多少个数字、多少个英文字母、多少个空白字符、多少个其他字符。

def count_str_char(my_str):
    digit_count = 0
    char_count = 0
    blank_count = 0
    other_count = 0
    for ch in my_str:
        if ch.isdigit():
            digit_count += 1
        elif ch.encode('utf-8').isalpha():
            char_count += 1
        elif ch.isspace():
            blank_count += 1
        else:
            other_count += 1
    return digit_count, char_count, blank_count, other_count
​
​
while(True):
    my_str = input('请输入一个字符串:')
    if my_str == 'exit':
        import sys
        sys.exit(0)
    digit_count, char_count, blank_count, other_count = count_str_char(my_str)
    print('字母个数:', char_count)
    print('数字个数', digit_count)
    print('空白个数:', blank_count)
    print('其他字符个数:', other_count)
5. 定义一个fn(n)函数,该函数返回1~n的立方和,即求1+2*2*2+3*3*3+…+n*n*n。



def fn(n):
    result = 0
    for i in range(n + 1):
        result += pow(i, 3)
    return result
​
​
while(True):
    n = input('请输入一个整数:')
    if n == 'exit':
        import sys
        sys.exit(0)
    if not n.isdigit():
        print('您输入的不是一个数字!')
        continue
    print('1~n的立方和为:', fn(int(n)))
           

6. 定义一个fn(n)函数,该函数返回n 的阶乘。

def fn(n):
    if n == 0:
        return 1
    if n == 1:
        return 1
    return n * fn(n-1)
​
​
while(True):
    n = input('请输入一个整数:')
    if n == 'exit':
        import sys
        sys.exit(0)
    if not n.isdigit():
        print('您输入的不是一个数字!')
        continue
    print('%s的阶乘是:%d' % (n, fn(int(n))))
           

7.  定义一个函数,该函数可接收一个list 作为参数,该函数用于去除list 中重复的元素。

def list_uniq(lst):
    temp_lst = set(lst)
    return list(temp_lst)
​
​
my_lst = [1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4]
print(list_uniq(my_lst))
           

8. 定义一个fn(n)函数,该函数返回一个包含n 个不重复的0~ 100 之间整数的元组。

import random
​
​
def fn(n):
    temp_lst = []
    for i in range(n):
        while(True):
            num = random.randint(0, 100)
            if num not in temp_lst:
                temp_lst.append(num)
                break
    return tuple(temp_lst)
​
​
print(fn(10))
           

9. 定义一个fn(n)函数,该函数返回一个包含n 个不重复的大写字母的元组。

import random
​
​
def fn(n):
    temp_lst = []
    for i in range(n):
        while(True):
            ch = chr(random.randint(65, 91))
            if ch not in temp_lst:
                temp_lst.append(ch)
                break
    return tuple(temp_lst)
​
​
print(fn(10))
           

10. 定义一个fn(n)函数,其中n 表示输入n 行n 列的矩阵(数的方阵〉。在输出时,先输出n行n 列的矩阵,再输出该矩阵的转置形式。例如,当参数为3 时,先输出:

1 2 3

4 5 6

7 8 9

再输出:

1 4 7

2 5 8

3 6 9

def fn(n):
    # 先输出n行n列的矩阵
    for i in range(n):
        for j in range(n):
            print(i * n + j + 1, end=' ')
        print()
    # 再输出转置矩阵
    for i in range(n):
        for j in range(n):
            print(j * n + i + 1, end=' ')
        print()
​
​
fn(3)
           

继续阅读