17.函数基础

目录

一、定义函数

1.函数基本结构

2.函数中的参数

(1)形参和实参

(2)默认参数

(3)不定长参数

3.函数的调用

(1)有参数、有返回值

(2)有参数、无返回值

(3)无参数、有返回值

(4)无参数、无返回值

二、函数实例-名片管理系统

1.主菜单显示:displayMenu()

2.主菜单选择:getChoice()

3.添加名片:addInfo()

4.删除名片:delinfo()

5.修改名片:changeInfo()

6.查询名片:seekInfo()

7.获取名片库中所有信息:showInfo()

8.动作选择:action_select()

9.主程序

三、变量作用域

1.全局变量和局部变量

2.global关键字

3.变量作用域

四、函数复杂结构

1.函数嵌套调用

2.嵌套函数

3.递归函数

五、函数练习

1.函数基础练习

2.寻找回文数

3.用户注册登陆系统

六、第十五课元组练习答案

1.元组基础练习

2.元组的解包

3.简单分析电影数据


函数是Python中最主要也是最重要的代码组织和重用方法。

如果您预期需要多次重复使用相同或非常相似的代码,那么编写一个可重用的函数将非常有价值。另外,将一段具有实现某个特定功能的代码用一个函数组织起来,可以帮助你的代码更具可读性。

一、定义函数

1.函数基本结构

(1)函数以def关键字作为开始,空一格是函数的名称并紧跟一对圆括号;

(2)函数名的命名规则和变量命名规则相同,即只能是字母、数字和下划线的组合且不能以数字开头,函数名不能与关键字或其他变量名重名;

(3)根据需要在圆括号内定义该函数的若干参数;

(4)函数体内语句以冒号:作为起始,并使用缩进;

(5)函数体内第一行可加注释语句,简要说明该函数的功能;

(6)使用return关键字返回值。

def 函数名称(参数1,参数2...):
    函数体内语句
return 表达式

示例1:
def my_function(x,y):
    return x+y

print(my_function(11,22))

示例2:
def my_function(x,y,z):
    if z>=1:
        return z*(x+y)
    else:
        return z/(x+y)
    
print(my_function(11,22,5))

2.函数中的参数

(1)形参和实参

形参:定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用,在函数外部不可使用。
实参:调用函数时,小括号中的参数,是用来把数据传递到函数内部用的参数。

(2)默认参数

定义函数时,可以给参数定义默认值,这个参数就被称为默认参数。(想想在学习字典的get()时,如果未查找到,将默认返回None。)

示例1:
def my_function(x,y,z=20):
    if y>=10:
        return z*(x+y)
    else:
        return z/(x+y)
    
print(my_function(11,22))

示例2:
def my_function(x, y, z=20):
    if y >= 10:
        return z * (x + y)
    else:
        return z / (x + y)


print(my_function(11, 22, 33))

在示例1的my_function函数中带了3个参数,其中z设置了默认值为20,在调用参数时,如果不设定第三个值(就像现在这样只有11,22这两个参数),则z将默认使用20。

在示例2中,调用函数时,指定了3个参数,把11,22,33分别传给x,y,z,这时的z不再使用默认值。

需要注意的时,默认参数只能位于参数的最后。

(3)不定长参数

通常不能预估将要处理的数据长度时,我们可以使用不定长参数。换句话说不定长参数可以帮我们解决函数定义时的参数个数可能少于需要实际处理的参数个数的情况。

def my_function(x,y,*z):
    print(x)
    print(y)
    print(z)

my_function(11,22,33,44,55,66,77,88,99)

# 输出
11
22
(33, 44, 55, 66, 77, 88, 99)

在my_function函数中,定义了3个参数,其中11,22传给x,y。在参数z前使用一个*号,将z设置为不定长参数,z接收其余的参数,并以元组保存在z中。

这种形式,在调用函数时最少传入2个参数,如果仅有2个参数,z将获得一个空元组。在定义参数时,不定长参数必须位于参数的最后。

如果传入的参数带有指定名称,我们可以使用2个*号定义不定长参数,该参数将以字典的形式存放这些被命名的参数。

def my_function(x,y,*id,**name): 
    print(x)
    print(y)
    print(id)
    print(name)

my_function(11,22,33,44,55,name1='Jim',name2='Tom') 

# 输出
11
22
(33, 44, 55)
 {'name1': 'Jim', 'name2': 'Tom'}
 

在定义函数时,一般的参数都简称为arg(argument),带*号的不定长参数简称为args,带**的不定长参数(关键字参数)简称为kwargs(keyword arguments)。

在定义函数时,args和kwargs的参数可以同时使用,也可以分别单独使用,如果同时使用,arg在左,其后是args,最后是kwargs。

在传入参数(调用函数)时,参数将按照从左向右的循序依次匹配函数定义时的参数,不定长参数可以缺省,如果有也遵循arg在左,其后是args,最后是kwargs的次序。否则会出现如下错误:

# 错误示例1
def my_function(x,y,*arg,**kwargs):
    print(x)
    print(y)
    print(arg)
    print(kwargs)

my_function(11,22,33,name='Tom',job = 'developer',1,2,3)

# 输出
  File "/Users/binhu/PycharmProjects/learnpython/temp.py", line 7
    my_function(11,22,33,name='Tom',job = 'developer',1,2,3)
                                                           ^
SyntaxError: positional argument follows keyword argument
 

3.函数的调用

函数遵循先定义后调用的原则,在程序内函数定义部分在前,函数调用部分在后。

函数定义后不会自动执行,只有遇到调用它的语句时才会执行。

函数调用有四种情况:

(1)有参数、有返回值

def my_function(x,y):
    return x+y


print(100 + my_function(11,22)) # 形式一:对返回的结果进一步处理
total = my_function(22,33) # 形式二:将返回的结果赋值给变量

print('total is %i'%total)

(2)有参数、无返回值

from random import randint
def my_function(numbers):
    for i in range(numbers):
        print(randint(0,100))
my_function(10)

(3)无参数、有返回值

def my_function():
    lst = [x for x in range(100) if x % 2 == 0]
    return lst
print(my_function())
 

(4)无参数、无返回值

def print_menu():
    print("-------- menu --------")
    menu = ['苹果','西瓜','香蕉','樱桃','菠萝']
    for i in range(len(menu)):
        print(i,menu[i])

print_menu()

二、函数实例-名片管理系统

名片管理系统实现简单的姓名添加、删除、修改、查询操作。该版本任务相比教材有一定变化,增加了任务的趣味性和挑战度。

功能结构:本项目主要由7个部分组成,它们分别是主菜单显示、主菜单选择和添加名片、删除名片、修改名片、查询名片、获取名片信息五个功能模块,根据用户的输入来选择进入对应的功能模块。我们将逐一构造7个函数来完成相应的动作。

------------------------------
       名片管理系统v.plus
1 添加名片
2 删除名片
3 修改名片
4 查询名片
5 获取所有名片信息
6 退出系统
------------------------------

1.主菜单显示:displayMenu()

该函数没有参数和返回值,在执行该函数后,将显示上图页面。第一行和最后一行都是由30个 - 横线组成的分割线,作为主菜单的框线,标题居中显示,显示模块的序号及名称。

程序运行后,首先运行该函数,等待用户的输入;在每个子模块运行结束后,重新返回该页面,再次等待用户输入,直到用户输入6退出系统,本程序结束运行。

函数代码:

def displayMenu():
    title = "名片管理系统v.plus"
    print("-"*30)
    print(title.center(30))
    menu = ['添加名片','删除名片','修改名片','查询名片','获取所有名片信息','退出系统']
    for i in range(len(menu)):
        print(i+1,menu[i])
    print("-"*30)

2.主菜单选择:getChoice()

该函数没有参数,但有返回值。

该函数使用一个input函数接收并对用户的输入序号作出判断:是否为数字?数字是否在选项范围内?如果用户输入的选项错误,给出提示并再次调用本函数等待用户输入,返回用户输入的序号。

def getChoice():
    selectKey = input("请输入你选择的序号:")
    if selectKey.isdigit():
        selectKey = int(selectKey)
    else:
        print("请输入正确的序号")
        getChoice()
    if selectKey not in range(1,7):
        getChoice()
    else:
        return selectKey

3.添加名片:addInfo()

该函数没有参数和返回值,但使用了全局变量namelist。

该函数将用户输入的姓名添加到namelist中(英文首字母大写)。

def addInfo():
    newName = input("请输入你要添加的姓名:").title()
    namelist.append(newName)

4.删除名片:delinfo()

该函数没有参数和返回值,但使用了全局变量namelist。

在运行该函数前,将先运行showinfo函数,显示namelist目前名片库中的信息。

该函数的作用是接收用户需要删除内容的序号,如果序号在namelist已有内容的序号范围内,则根据索引将其删除,如果序号错误,重新调用delinfo函数。

def delInfo():
    index = int(input("请输入你要删除的序号:"))
    if index not in range(1,len(namelist)+1):
        delInfo()
    else:
        namelist.pop(index-1)

5.修改名片:changeInfo()

该函数没有参数和返回值,但使用了全局变量namelist。

提示"请输入你要修改的姓名,按回车结束",将用户输入的内容标题化后存入name中,判断namelist中是否存在该姓名,如果存在提示用户输入新的姓名,并根据下标将原内容修改为新值;如果不存在则提示“该姓名不存在”。

def changeInfo():
    name = input("请输入你要修改的姓名,按回车结束").title()
    if namelist.count(name) > 0:
        newname = input("请输入新的姓名,按回车结束").title()
        namelist[namelist.index(name)] = newname
    else:
        print('%s不存在'%delname)

6.查询名片:seekInfo()

该函数没有参数和返回值,但使用了全局变量namelist。

将用户的输入标题化后保存在name中,判断namelist中是否存在name,如果存在显示name在namelist中的下标及值,否则提示"该姓名不存在"

def seekinfo():
    name = input("请输入你要查找人的姓名,按回车结束").title()
    if namelist.count(name) > 0:
        print(namelist.index(name),name)
    else:
        print('%s不存在'%name)

7.获取名片库中所有信息:showInfo()

该函数没有参数和返回值,但使用了全局变量namelist。

------------------------------
             名片列表             
1 Tom
2 Jim
3 Cheryl
4 Susan
------------------------------

在执行该函数后,将显示上图页面。第一行和最后一行都是由30个 - 横线组成的分割线,作为主菜单的框线,标题居中显示。依次输出namelist已有信息的序号和姓名。

def showInfo():
    print("-"*30)
    i = 1
    print("名片列表".center(30))
    for k in namelist:
        print(i,k)
        i += 1
    print("-"*30)

8.动作选择:action_select()

该函数有一个参数,没有返回值。

根据getChoice函数返回的选项序号,执行相应动作。key==1,执行addInfo函数;key==2,执行showInfo函数和delInfo函数;key==3,执行showInfo函数和changeInfo函数;key==4,执行seekInfo函数;key==5,执行showInfo函数;key==6,执行exit(),退出程序;key等于其他值,提示用户输入正确的序号。

def action_select(key):
    if key == 1:
        addInfo()
    elif key == 2:
        showInfo()
        delInfo()
    elif key == 3:
        showInfo()
        changeInfo()
    elif key == 4:
        seekinfo()
    elif key == 5:
        showInfo()
    elif key == 6:
        exit()
    else:
        print("请输入正确的序号")

9.主程序

主程序循环执行三个动作:显示主菜单(displayMenu)、获取用户输入的选项序号(getChoice)、对选项序号进行判断激活相应的函数(action_select)。另外,在主程序中添加了namelist为全局变量。

namelist = []

while True:
    displayMenu()
    key = getChoice()
    action_select(key)

三、变量作用域

1.全局变量和局部变量

全局变量和局部变量的区别在于作用域,全局变量在整个py文件中声明,全局范围内可以使用;局部变量是在某个函数内部声明的,只能在函数内部使用,如果超出使用范围(函数外部),则会报错。

def my_function():
    a = 50
    print(a+b)

b = 100
my_function()
print(b)
print(a)

# 输出
150
100
Traceback (most recent call last):
  File "/Users/binhu/PycharmProjects/learnpython/test.py", line 8, in <module>
    print(a)
NameError: name 'a' is not defined

在上面的列子中,变量a在函数内定义,是局部变量,只能在my_function函数内使用;b在函数外定义,是全局变量,可以在全局范围内使用。该实例在函数外print(a)发生错误。

我们再看一个例子,在函数中是否可以修改全局变量b的值。

def my_function():
    a = 50
    b += a
    print(b)

b = 100
my_function()

# 输出
Traceback (most recent call last):
  File "/Users/binhu/PycharmProjects/learnpython/test.py", line 7, in <module>
    my_function()
  File "/Users/binhu/PycharmProjects/learnpython/test.py", line 3, in my_function
    b += a
UnboundLocalError: local variable 'b' referenced before assignment

我们发现,在函数内虽然可以使用全局变量b,如果重新赋值就会报错。这是因为如果在函数内对变量赋值,python会自动将变量默认为函数中的局部变量。因此b就成为了my_function中的局部变量,又因为b未提前赋值就在b += a(等同于b = b+a)中被引用,从而发生错误。如果想在函数内对全局变量进行操作,需要使用到global关键字。

2.global关键字

def my_function():
    a = 50
    global b
    b += a
    print(b)

b = 100
my_function()
print(b)

# 输出
150
150

global告诉python这里引用的全局变量b,并通过b+=a对b重新赋值。

进一步探究发现,在函数内操作字符串、数字、元组等不能原地改变的不可变类型的全局变量,如果想在函数内改变这些变量的同时修改函数外的变量,必须使用global。而对于列表、字典等可变类型,如果只是修改而不是重新赋值,则不受此限制。

def my_function():
    global a
    a = a + 10
    b.append(10)
    c[1]='c'
    print('this is in the funciton',id(a),a)
    print('this is in the funciton',id(b),b)
    print('this is in the funciton',id(c),c)


a = 100
b = [1,2,3]
c = {1:'a',2:'b'}

print(id(a),a)
print(id(b),b)
print(id(c),c)

my_function()

print(id(a),a)
print(id(b),b)
print(id(c),c)

# 输出
4488340944 100
4489388288 [1, 2, 3]
4489321344 {1: 'a', 2: 'b'}
this is in the funciton 4488341264 110
this is in the funciton 4489388288 [1, 2, 3, 10]
this is in the funciton 4489321344 {1: 'c', 2: 'b'}
4488341264 110
4489388288 [1, 2, 3, 10]
4489321344 {1: 'c', 2: 'b'}

3.变量作用域

通过以上的几个例子中,我们能体会到创建的变量并不是在哪里都能访问,访问权限决定于这个变量是在哪里赋值的,这就涉及到变量作用域的问题。

在python中变量作用域采用“LEGB”的查找原则,即python在检索变量的时候,会优先在函数作用域中查找,如果没有找到,便会去外层函数作用域中查找,再找不到就会去全局作用域查找,最后再去内建作用域中找。

L(Local):函数内的取余,包括局部变量和参数;

E(Enclosing):外层嵌套函数区域,常见的是闭包函数的外层函数;

G(Global):全局作用域;

B(Bulit-in):内建作用域。

四、函数复杂结构

1.函数嵌套调用

在一个函数内嵌套调用了另一个函数,这就是所谓的函数嵌套调用。

def function_1():
    print('this is function 1 start')
    print('*' * 25)
    print('this is function 1 end')

def function_2():
    print('this is function 2 start')
    function_1()
    print('this is function 2 end')

function_2()

# 输出
this is function 2 start
this is function 1 start
*************************
this is function 1 end
this is function 2 end

2.嵌套函数

函数在定义时,一个函数嵌套了另一个函数称为嵌套函数。

def func_out(): # 外层函数开始
    a = 10
    def func_in(): # 内层函数开始
        b = 20
        print(a)
        print(b) # 内层函数结束
    func_in() # 外层函数结束
func_out()

# 输出
10
20

请大家思考下面语句的输出是什么?

def func_out(): # 外层函数开始
    a = 10
    def func_in(): # 内层函数开始
        b = 20
        a = 30
        print(a,id(a))
        print(b,id(b)) # 内层函数结束
    func_in()
    print(a,id(a)) # 外层函数结束
func_out()

# 输出
30 4399910096
20 4399909776
10 4399909456

外层函数定义了1个变量a,内层函数定义了2个变量a、b,内外层的变量a变量名相同、作用域不同、指向的内存也不同。在内层中a=30的赋值并没有改变外层a的值,而是在内层函数中重新定义了一个同名的变量a。若要修改外层变量a的值,可使用nonlocal关键字。

def func_out(): # 外层函数开始
    a = 10
    def func_in(): # 内层函数开始
        b = 20
        nonlocal a
        a = 30
        print(a,id(a))
        print(b,id(b)) # 内层函数结束
    func_in()
    print(a,id(a)) # 外层函数结束
func_out()

# 输出
30 4466228432
20 4466228112
30 4466228432

3.递归函数

函数嵌套调用是在一个函数的内部调用其他函数,如果在一个函数的内部调用了函数本身,那么这个函数称为递归函数。 

在“14.列表从入门到实践”有一道练习是要对多层嵌套列表中的所有值求和,如下所示。

当时我们解决这个问题的思路是逐级遍历元素并判断类型是否为列表,如果是列表则将其展开,最终实现所有元素的展开。为此我们设计了3层循环和2次if判断,如下所示。

看似我们解决了这个问题,但是如果嵌套的层数变多,我们的代码结构将变得异常复杂。

但我们使用递归函数,将可以大幅优化我们的代码结构。

lst	= [11, 22, 33, [44, 55, 66, 77, [88, 99, 100, 110]]]

summary = 0
for x in lst:
    if isinstance(x,list):
        for y in x:
            if isinstance(y,list):
                for z in y:
                    summary += z
            else:
                summary += y
    else:
        summary += x
print(summary)

使用递归函数展开多层嵌套列表。

new_list = [] # 用来存放嵌套列表中的每一个元素,结果将是lst展开后的结果。
def flatten_list(lst): # 定义一个函数,该函数是递归函数
    for x in lst: # 循环遍历lst
        if isinstance(x,list): # 判断该元素的类型是否为列表
            flatten_list(x) # 如果是列表,则调用函数自身
        else:
            new_list.append(x) # 如果不是,则将该元素添加到新的列表中
flatten_list(lst) # 调用函数
print(sum(new_list)) # 对展开后的列表求和

五、函数练习

1.函数基础练习

# 任务1:lst中有[1,2,3,4,5,6,7,8,9],定义一个名为add_odd()的函数,参数为x用以接收lst,在函数中将所有奇数存到一个新的列表中,返回给调用函数,并计算输出新列表的和。
# 在此处下方定义add_odd()

lst = [1,2,3,4,5,6,7,8,9]

# 在此处次方编写函数调用语句


# 任务2:写一个函数,判断用户传入的对象长度是否大于5


# 任务3:编写函数,求“1/(1*2)-1/(2*3)+1/(3*4)-1/(4*5)+……”前n项的和,将n作为参数,n由用户输入。

2.寻找回文数

回文数是一个正向和逆向都相同的数,如12321、7887等,请编写函数找出1到n之间的所有回文数,并将其存入列表中打印出来。将n作为参数,n由用户输入。

3.用户注册登陆系统

编写一段程序实现简单的用户注册登陆,要求如下:

子任务1:创建一个名为displaymenu的函数,展示如下图所示的系统菜单。
******************************
        用户注册登陆系统       
1 用户注册
2 用户登陆
3 退出系统
******************************

子任务2:创建一个名为getchoice的函数,提示“请选择您想要操作的序号”。要求对用户输入序号的正确性进行判断,如果序号正确,则返回该序号的整形。

子任务3:创建一个名为user_register的函数,提示用户依次输入用户名、密码、确认密码,并对以上信息按以下规则依次进行检查:
(1)用户名不重复,且以字母开头、用户名长度在6到30位之间,可包含字母、数字和下划线,以小写保存。
(2)密码不得少于6位,包含字母、数字和下划线其中至少2种。
(3)确认密码与输入密码必须一致。
(4)注册成功时提示用户已成功注册。
其他要求:检验发现格式错误的,应给予用户错误提示,直到用户注册成功才退回到系统菜单页面。用户名和密码以{username:(username,password)}键值对的形式存储在名为userinfo的字典中。

子任务4:创建一个名为user_logo的函数,提示用户依次输入用户名、密码,并对以上信息按以下规则依次进行验证:
(1)检查用户名是否已存在于userinfo中,如果不存在,则提示该用户名不存在。
(2)继续判断用户名匹配的密码是否一直,如果不匹配则提示密码错误。
(3)登陆成功时提示用户成功登陆。

子任务5:主程序
(1)调用showmenu函数
(2)调用getchoice函数并获得用户的输入
(3)根据用户的输入分别匹配调用user_register、user_logo函数,如果用户输入3,则退出本程序。

六、第十五课元组练习答案

1.元组基础练习

# 1.创建一个元组,里面包含1到5之间的所有整数,并将其赋值给变量tup1,输出tup1的值。
tup1 = tuple(range(1,6))
print(tup1)
# 2.创建一个元组,里面包含1个元素‘tuple’,并将其赋值给变量tup2,输出tup2的值。
tup2 = ('tuple',)
print(tup2)
# 3.创建一个元组,里面包含1到50之间的所有奇数,并将其赋值给变量tup3,输出tup3的值。
tup3 = tuple([x for x in range(1,51,2)])
print(tup3)
# 4.输出tup3中的第7位。
print(tup3[6])
# 5.输出tup3中的第12到17位。
print(tup3[11:17])
# 6.输出tup3中的后8位。
print(tup3[-8:])
# 7.将tup3的后10位删除,并保存为tup4。
tup4 = tup3[0:-10]
print(tup4)
# 8.将tup4中第5位修改为[77,88,99],并保存为tup5。
tup5 = list(tup4)
tup5[4] = [77,88,99]
tup5 = tuple(tup5)
print(tup5)
# 9.输出88,99
print(tup5[4][1:])
# 10.在tup5中的99后面新增100。
tup5[4].append(100)
print(tup5)

2.元组的解包

'''
有一批手工制作的箱子,一共50个,他们大小不一。请编程计算这批箱子的总体积和平均体积。
data中一共有50个元组,每个元组有3个数值,分别对应长、宽、高。
Your Mission:
1.循环遍历列表中的元组;
2.在循环体内,通过元组解包将三个数值同时分别赋值length,width,height三个变量;
3.计算每个箱子的体积,并将结果存到一个新的列表V中;
4.计算列表V中所有数值的和(即总体积)以及列表V的长度;
5.计算并输出平均体积。

'''

data = [(87, 71, 70), (100, 61, 70), (80, 77, 80), (95, 73, 73), (97, 70, 65), (95, 65, 68), (92, 65, 66), (100, 79, 76), (85, 61, 80), (91, 71, 71), (91, 60, 79), (80, 70, 68), (83, 65, 78), (81, 70, 67), (85, 80, 75), (86, 66, 60), (83, 70, 69), (80, 79, 67), (96, 67, 67), (90, 70, 60), (90, 74, 71), (89, 68, 65), (84, 68, 66), (92, 68, 74), (92, 70, 64), (96, 65, 73), (100, 62, 77), (87, 74, 63), (100, 74, 71), (89, 64, 74), (88, 65, 79), (96, 63, 67), (89, 69, 71), (88, 74, 75), (88, 75, 73), (93, 75, 72), (87, 76, 64), (90, 74, 80), (81, 80, 76), (98, 65, 74), (88, 70, 67), (89, 69, 76), (82, 71, 71), (93, 68, 73), (92, 62, 64), (91, 77, 65), (96, 80, 76), (81, 68, 69), (91, 65, 78), (96, 62, 62)]
v = []
for length,width,height in data:
    v.append(length * width * height)
print(sum(v),len(v))
print(sum(v)/len(v))

3.简单分析电影数据

data = [('Avatar', 7.9, 'CCH Pounder', 'Joel David Moore', 'Wes Studi'), ("Pirates of the Caribbean: At World's End", 7.1, 'Johnny Depp', 'Orlando Bloom', 'Jack Davenport'), ('Spectre', 6.8, 'Christoph Waltz', 'Rory Kinnear', 'Stephanie Sigman'), ('The Dark Knight Rises', 8.5, 'Tom Hardy', 'Christian Bale', 'Joseph Gordon-Levitt'), ('Star Wars: Episode VII - The Force Awakens', 7.1, 'Doug Walker', 'Rob Walker', "Nan"), ('John Carter', 6.6, 'Daryl Sabara', 'Samantha Morton', 'Polly Walker'), ('Spider-Man 3', 6.2, 'J.K. Simmons', 'James Franco', 'Kirsten Dunst'), ('Tangled', 7.8, 'Brad Garrett', 'Donna Murphy', 'M.C. Gainey'), ('Avengers: Age of Ultron', 7.5, 'Chris Hemsworth', 'Robert Downey Jr.', 'Scarlett Johansson'), ('Harry Potter and the Half-Blood Prince', 7.5, 'Alan Rickman', 'Daniel Radcliffe', 'Rupert Grint'), ('Batman v Superman: Dawn of Justice', 6.9, 'Henry Cavill', 'Lauren Cohan', 'Alan D. Purwin'), ('Superman Returns', 6.1, 'Kevin Spacey', 'Marlon Brando', 'Frank Langella'), ('Quantum of Solace', 6.7, 'Giancarlo Giannini', 'Mathieu Amalric', 'Rory Kinnear'), ("Pirates of the Caribbean: Dead Man's Chest", 7.3, 'Johnny Depp', 'Orlando Bloom', 'Jack Davenport'), ('The Lone Ranger', 6.5, 'Johnny Depp', 'Ruth Wilson', 'Tom Wilkinson'), ('Man of Steel', 7.2, 'Henry Cavill', 'Christopher Meloni', 'Harry Lennix'), ('The Chronicles of Narnia: Prince Caspian', 6.6, 'Peter Dinklage', 'Pierfrancesco Favino', 'Damián Alcázar'), ('The Avengers', 8.1, 'Chris Hemsworth', 'Robert Downey Jr.', 'Scarlett Johansson'), ('Pirates of the Caribbean: On Stranger Tides', 6.7, 'Johnny Depp', 'Sam Claflin', 'Stephen Graham'), ('Men in Black 3', 6.8, 'Will Smith', 'Michael Stuhlbarg', 'Nicole Scherzinger'), ('The Hobbit: The Battle of the Five Armies', 7.5, 'Aidan Turner', 'Adam Brown', 'James Nesbitt'), ('The Amazing Spider-Man', 7.0, 'Emma Stone', 'Andrew Garfield', 'Chris Zylka'), ('Robin Hood', 6.7, 'Mark Addy', 'William Hurt', 'Scott Grimes'), ('The Hobbit: The Desolation of Smaug', 7.9, 'Aidan Turner', 'Adam Brown', 'James Nesbitt'), ('The Golden Compass', 6.1, 'Christopher Lee', 'Eva Green', 'Kristin Scott Thomas'), ('King Kong', 7.2, 'Naomi Watts', 'Thomas Kretschmann', 'Evan Parke'), ('Titanic', 7.7, 'Leonardo DiCaprio', 'Kate Winslet', 'Gloria Stuart'), ('Captain America: Civil War', 8.2, 'Robert Downey Jr.', 'Scarlett Johansson', 'Chris Evans'), ('Battleship', 5.9, 'Liam Neeson', 'Alexander Skarsgård', 'Tadanobu Asano'), ('Jurassic World', 7.0, 'Bryce Dallas Howard', 'Judy Greer', 'Omar Sy'), ('Skyfall', 7.8, 'Albert Finney', 'Helen McCrory', 'Rory Kinnear'), ('Spider-Man 2', 7.3, 'J.K. Simmons', 'James Franco', 'Kirsten Dunst'), ('Iron Man 3', 7.2, 'Robert Downey Jr.', 'Jon Favreau', 'Don Cheadle'), ('Alice in Wonderland', 6.5, 'Johnny Depp', 'Alan Rickman', 'Anne Hathaway'), ('X-Men: The Last Stand', 6.8, 'Hugh Jackman', 'Kelsey Grammer', 'Daniel Cudmore'), ('Monsters University', 7.3, 'Steve Buscemi', 'Tyler Labine', 'Sean Hayes'), ('Transformers: Revenge of the Fallen', 6.0, 'Glenn Morshower', 'Kevin Dunn', 'Ramon Rodriguez'), ('Transformers: Age of Extinction', 5.7, 'Bingbing Li', 'Sophia Myles', 'Kelsey Grammer'), ('Oz the Great and Powerful', 6.4, 'Tim Holmes', 'Mila Kunis', 'James Franco'), ('The Amazing Spider-Man 2', 6.7, 'Emma Stone', 'Andrew Garfield', 'B.J. Novak'), ('TRON: Legacy', 6.8, 'Jeff Bridges', 'Olivia Wilde', 'James Frain'), ('Cars 2', 6.3, 'Joe Mantegna', 'Thomas Kretschmann', 'Eddie Izzard'), ('Green Lantern', 5.6, 'Ryan Reynolds', 'Temuera Morrison', 'Taika Waititi'), ('Toy Story 3', 8.3, 'Tom Hanks', 'John Ratzenberger', 'Don Rickles'), ('Terminator Salvation', 6.6, 'Christian Bale', 'Bryce Dallas Howard', 'Common'), ('Furious 7', 7.2, 'Jason Statham', 'Paul Walker', 'Vin Diesel'), ('World War Z', 7.0, 'Peter Capaldi', 'Brad Pitt', 'Mireille Enos'), ('X-Men: Days of Future Past', 8.0, 'Jennifer Lawrence', 'Peter Dinklage', 'Hugh Jackman'), ('Star Trek Into Darkness', 7.8, 'Benedict Cumberbatch', 'Bruce Greenwood', 'Noel Clarke'), ('Jack the Giant Slayer', 6.3, 'Eddie Marsan', 'Ewen Bremner', 'Ralph Brown')]
'''
data是从IMDB爬取的5000条电影数据集的其中50部电影的数据,并只截取了其中5个字段的数据,这些字段分别是电影名称(movie_name)、IMDB评分(imdb_scores)、第一主演姓名(actor_1_name)、第二主演姓名(actor_2_name)、第三主演姓名(actor_3_name),每部电影的数据存在一个元组中。
 
Your Mission:
1.循环遍历列表中的元组。
2.在循环时,你要完成以下子任务:
(1)完成对每个元组的解包,将元组的第1项赋给name, 第2项赋给scores, 其余的赋给actors;(希望你还记得怎么使用*)
(2)接下来将(name,scores)存入到movies_scores的列表中
(3)将actors中的内容存入到movies_actors的列表中。(你要判断一下append、insert、extend哪个最适合用来完成此任务)
*记住,这些都是在循环中完成的。
3.Boss级的任务来了,你准备好了吗?
(1)我需要你帮助我找到movies_scores中评分最高的前10部电影(仅用1行代码)。以下是你应该得到的结果(这些电影我都超爱,怪不得评分这么高,嘿嘿~):
[('The Dark Knight Rises', 8.5), ('Toy Story 3', 8.3), ('Captain America: Civil War', 8.2), ('The Avengers', 8.1), ('X-Men: Days of Future Past', 8.0), ('Avatar', 7.9), ('The Hobbit: The Desolation of Smaug', 7.9), ('Tangled', 7.8), ('Skyfall', 7.8), ('Star Trek Into Darkness', 7.8)]
 
(2)此外,我还希望知道这50部电影中,谁出演过的电影数最多,将参演电影数最多的前10位演员及参演电影的数量一并输出。以下是你应该得到的结果:(这题稍微有点超纲,会用到之后章节字典中的一些知识,你可以在网上检索相关技巧)
[('Johnny Depp', 5), ('Robert Downey Jr.', 4), ('Rory Kinnear', 3), ('James Franco', 3), ('Scarlett Johansson', 3), ('Orlando Bloom', 2), ('Jack Davenport', 2), ('Christian Bale', 2), ('J.K. Simmons', 2), ('Kirsten Dunst', 2)]
'''
movies_scores = []
movies_actors = []
for name,scores,*actors in data:
    movies_scores.append((name,scores))
    movies_actors.extend(actors)
print(sorted(movies_scores,key = lambda x:x[1],reverse=True)[:10])

D = {}
for name in movies_actors:
    if name in D.keys():
        D[name] += 1
    else:
        D[name] = 1
print(sorted(D.items(),key = lambda x:x[1],reverse=True)[:10])

猜你喜欢

转载自blog.csdn.net/qq_40407729/article/details/111576879