datawhale Python Day6

综述:今天将学习函数。函数是带名字的代码块,用于完成具体工作。要执行函数定义的特定任务,可调用该函数。需要在程序中多次执行一项任务时,我们无需反复编写该任务的代码,而只需调用执行该任务的函数即可。通过使用函数,程序的编写、阅读、测试和修复都将更加容易。
1.1 定义函数
示例1:打印问候语

def greet_user():
    print('Hello!')
greet_user()
#输出结果:
Hello!

使用关键字def 来告诉Python你要定义一个函数。这是函数定义 ,向Python指出了函数名,还可能在括号内指出函数为完成其 任务需要什么样的信息。在这里,函数名为greet_user() ,它不需要任何信息就能完成其工作,因此括号是空的(即便如此,括号也必不可少)。最后,定义以冒号结尾。
代码行print(“Hello!”) 是函数体内的唯一一行代码,greet_user() 只做一项工作:打印Hello! 。要使用这个函数,可调用它。函数调用让Python执行函数的代码。要调用函数,可依次指定函数名以及用括号括起的必要信息,由于这个函数不需要任何信息,因 此调用它时只需输入greet_user() 即可。和预期的一样,它打印Hello!
1.2 实参和形参
只需稍作修改,就可以让函数greet_user() 不仅向用户显示Hello! ,还将用户的名字用作抬头。为此,可在函数定义def greet_user() 的括号内添加username 。通 过在这里添加username ,就可让函数接受你给username 指定的任何值。现在,这个函数要求你调用它时给username 指定一个值。调用greet_user() 时,可将一个名字传递给它。

def greet_user(username):
    print('Hello, "+username.title()+'!')
greet_user('jesse')
#输出结果:
Hello, Jesse!

前面定义函数greet_user() 时,要求给变量username 指定一个值。调用这个函数并提供这种信息(人名)时,它将打印相应的问候语。在函数greet_user() 的定义中,变量username 是一个形参 ——函数完成其工作所需的一项信息。在代码greet_user(‘jesse’) 中,值’jesse’ 是一个实参 。实参是调用函数时传递给函数的信息。我们调用函数时,将要让函数使用的信息放在括号内。在greet_user(‘jesse’) 中,将实参’jesse’ 传递给了函数greet_user() ,这个值被存储在形参username 中。
1.2.1 位置实参
你调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参 位置实参 。
为明白其中的工作原理,来看一个显示宠物信息的函数。这个函数指出一个宠物属于哪种动物以及它叫什么名字,如下所示:

def describe_pet(animal_type,pet_name):
    print('I have a '+animal_type)
    print('My '+animal_type+'' 's name is ''+pet_name)
describe_pet('hamster','harry')
#输出结果:
I have a hamster
My hamster's name is harry

位置实参的顺序很重要,需要确认函数调用中实参的顺序与函数定义中形参的顺序一致。
1.2.2 关键字实参
关键字实参是传递给函数的名称—值对。你直接在实参中将名称和值关联起来了,因此向函数传递实参时不会混淆(不会得到名为Hamster的harry这样的结果)。关键字实参让你无需考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值的用途。

def describe_pet(animal_type,pet_name):
    print('I have a '+animal_type)
    print('It called '+pet_name)
describe_pet(animal_type='hamster',pet_name='harry')
#输出结果:
I have a hamster
It called harry

函数describe_pet() 还是原来那样,但调用这个函数时,我们向Python明确地指出了各个实参对应的形参。看到这个函数调用时,Python知道应该将实参’hamster’ 和’harry’ 分别存储在形参animal_type 和pet_name 中。输出正确无误,它指出我们有一只名为Harry的仓鼠。 关键字实参的顺序无关紧要,因为Python知道各个值该存储到哪个形参中。下面两个函数调用是等效的:

describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(pet_name='harry', animal_type='hamster')

注意:使用关键字形参时,务必准确地指定函数定义中的形参名。
1.2.3 默认值
编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时,Python将使用指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。 例如,如果你发现调用describe_pet() 时,描述的大都是小狗,就可将形参animal_type 的默认值设置为’dog’ 。这样,调用describe_pet() 来描述小狗时,就可不提供这种信息:

def  desceibe_pet(pet_name,animal_type='dog'):
       print('I have a '+animal_type)
       print('It called '+pet_name)
 describe_pet('willie')
 #输出结果:
I have a dog
It called willie

这里修改了函数describe_pet() 的定义,在其中给形参animal_type 指定了默认值’dog’ 。这样,调用这个函数时,如果没有给animal_type 指定值,Python将把这个形参设置为’dog’ 。请注意,在这个函数的定义中,修改了形参的排列顺序。由于给animal_type 指定了默认值,无需通过实参来指定动物类型,因此在函数调用中只包含一个实参——宠物的名字。然而,Python依然将这个实参视为位置实参,因此如果函数调用中只包含宠物的名字,这个实参将关联到函数定义中的第一个形参。这就是需要将pet_name 放在形参列表 开头的原因所在。
1.3 返回值
函数并非总是直接显示输出,相反,它可以处理一些数据,并返回一个或一组值。函数返回的值被称为返回值 返回值 。在函数中,可使用return 语句将值返回到调用函数的代码行。 返回值让你能够将程序的大部分繁重工作移到函数中去完成,从而简化主程序。

def get_formatted_name(first_name,last_name):
    full_name=first_name+' '+last_name
    return full_name
musician=get_formatted_name('Tracy','Mcgrady')
print(musician)
#输出结果:
Tracy Mcgrady

函数get_formatted_name() 的定义通过形参接受名和姓。它将姓和名合而为一,在它们之间加上一个空格,并将结果存储在变量full_name 中。然后,将full_name 的值转换为首字母大写格式,并将结果返回到函数调用行。调用返回值的函数时,需要提供一个变量,用于存储返回的值。在这里,将返回值存储在了变量musician 中。输出为整洁的姓名。
1.3.1 让实参变成可选的
有时候,需要让实参变成可选的,这样使用函数的人就只需在必要时才提供额外的信息。可使用默认值来让实参变成可选的。
假设我们要扩展函数get_formatted_name() ,使其还处理中间名。为此,可将其修改成类似于下面这样:

def get_formatted_name(first_name,middle_name,last_name):
    full_name=first_name+' '+middle_name+' '+last_name
    return full_name
musician=get_formatted_name('john','lee','hooker')
print(musician)
#输出结果:
john lee hooker

然而,并非所有的人都有中间名,但如果你调用这个函数时只提供了名和姓,它将不能正确地运行。为让中间名变成可选的,可给实参middle_name 指定一个默认值——空字 符串,并在用户没有提供中间名时不使用这个实参。为让get_formatted_name() 在没有提供中间名时依然可行,可给实参middle_name 指定一个默认值——空字符串, 并将其移到形参列表的末尾:

def get_formatted_name(first_name,last_name,middle_name=' '):
    if middle_name:
       full_name=first_name+' '+middle_name+' '+last_name
    else:
       full_name=first_name+' '+last_name
return full_name
musician=get_formatted_name('jimi','hendrix')
print(musician)
musician=get_formatted_name('john','hooker','lee')
print(musician)
#输出结果:
jimi   hendrix
john lee hooker

在这个示例中,姓名是根据三个可能提供的部分创建的。由于人都有名和姓,因此在函数定义中首先列出了这两个形参。中间名是可选的,因此在函数定义中最后列出该形参, 并将其默认值设置为空字符串。 在函数体中,我们检查是否提供了中间名。Python将非空字符串解读为True ,因此如果函数调用中提供了中间名,if middle_name 将为True 。如果提供了中间 名,就将名、中间名和姓合并为姓名,然后将其修改为首字母大写格式,并返回到函数调用行。在函数调用行,将返回的值存储在变量musician 中;然后将这个变量的值打印 出来。如果没有提供中间名,middle_name 将为空字符串,导致if 测试未通过,进而执行else 代码块:只使用名和姓来生成姓名,并将设置好格式的姓名返回给函 数调用行。在函数调用行,将返回的值存储在变量musician 中;然后将这个变量的值打印出来。 调用这个函数时,如果只想指定名和姓,调用起来将非常简单。如果还要指定中间名,就必须确保它是最后一个实参,这样Python才能正确地将位置实参关联到形参。
1.3.2 返回字典
函数可返回任何类型的值,包括列表和字典等较复杂的数据结构。例如,下面的函数接受姓名的组成部分,并返回一个表示人的字典:

def build_person(first_name,last_name):
    person={'first':first_name,'last':last_name}
    return person
musician=build_person('jimi','hendrix')
print(musician)
#输出结果:
{'first': 'jimi', 'last': 'hendrix'}

函数build_person() 接受名和姓,并将这些值封装到字典中。存储first_name 的值时,使用的键为’first’ ,而存储last_name 的值时,使用的键 为’last’ 。最后,返回表示人的整个字典。打印这个返回的值,此时原来的两项文本信息存储在一个字典中。
这个函数接受简单的文本信息,将其放在一个更合适的数据结构中,让你不仅能打印这些信息,还能以其他方式处理它们。当前,字符串’jimi’ 和’hendrix’ 被标记为名和 姓。你可以轻松地扩展这个函数,使其接受可选值,如中间名、年龄、职业或你要存储的其他任何信息。例如,下面的修改让你还能存储年龄:

def build_person(first_name,last_name,age=''):
    person={'first':first_name,'last':last_name}
    if age:
       person['age']=age
    return person
musician=build_person('jimi','hendrix',27)
print(musician)
#输出结果:
{'first': 'jimi', 'last': 'hendrix', 'age': 27}

1.3.3 结合使用函数和while循环
可将函数同本书前面介绍的任何Python结构结合起来使用。例如,下面将结合使用函数get_formatted_name() 和while 循环,以更正规的方式问候用户。下面尝试使用名 和姓跟用户打招呼:

def get_formatted_name(first_name,last_name):
    full_name=first_name+' '+last_name
    return full_name
while True:
    print('please tell me your name:')
    f_name=input('First name:')
    l_name=input('Last name:')
    formatted_name=get_formatted_name(f_name,l_name)
    print('Hello, '+formatted_name+'!')
#输出结果:
please tell me your name:
First name:kobe
Last name:bryant
Hello, kobe bryant!
please tell me your name:
First name:tracy
Last name:mcgrady
Hello, tracy mcgrady!
please tell me your name:
First name:   

在这个示例中,我们使用的是get_formatted_name() 的简单版本,不涉及中间名。其中的while 循环让用户输入姓名:依次提示用户输入名和姓。 但这个while 循环存在一个问题:没有定义退出条件。请用户提供一系列输入时,该在什么地方提供退出条件呢?我们要让用户能够尽可能容易地退出,因此每次提示用户输入 时,都应提供退出途径。每次提示用户输入时,都使用break 语句提供了退出循环的简单途径:

def get_formatted_name(first_name,last_name):
    full_name=first_name+' '+last_name
    return full_name
while True:
    print('please tell me your name:')
    print('enter 'q' at any time to quit)
    f_name=input('First name:')
    if f_name=='q':
       break
    l_name=input('Last name:')
    if l_name=='q':
      break
    formatted_name=get_formatted_name(f_name,l_name)
    print('Hello, '+formatted_name+'!')

我们添加了一条消息来告诉用户如何退出,然后在每次提示用户输入时,都检查他输入的是否是退出值,如果是,就退出循环。现在,这个程序将不断地问候,直到用户输入的 姓或名为’q’ 为止。
1.4 函数作用域
在被调用函数内赋值的变量,处于该函数的“局部作用域”。在所有函数之外赋值的变量,属于“全局作用域”。
一个函数被调用时,就创建了一个局部作用域。在这个函数内赋值的所有变量,存在于该局部作用域内。该函数返回时,这个局部作用域就被销毁了,这些变量就丢失了。下次调用这个函数,局部变量不会记得该函数上次被调用时它们保存的值。
局部变量不能在全局作用域内使用
局部作用域不能使用其他局部作用域内的变量
全局变量可以在局部作用域中读取
名称相同的局部变量和全局变量调用(优先调取局部变量,若找不到则寻找全局变量)
如果需要在一个函数内修改全局变量,就使用 global 语句。
1.5 魔法变量*args和**kwargs
*args 和 **kwargs 主要⽤于函数定义,可以将不定数量的参数传递给⼀个函数。不定的意思是:预先并不知道, 函数使⽤者会传递多少个参数给你, 所以在这个场景下使⽤这两个关键字。
*args 是⽤来发送⼀个⾮键值对的可变数量的参数列表、元组给⼀个函数。
**kwargs 是⽤来发送⼀个键值对的可变数量的参数字典给⼀个函数。
作业:
实现random.sample方法
实现Max方法
实现判断两个字符串是否相等的方法
1.python中random.sample()方法可以随机地从指定列表中提取出N个不同的元素。
例如:

import random
nums=range(10)
a=random.sample(list,2)
print(a)
#输出结果:
[9, 6]
import random
list=[1,2,3,4,5,6,7,8,9]
a=random.sample(list,2)
print(a)
#输出结果:
[5, 9]
import random
string='helloworld'
a=random.sample(string,2)
print(a)
#输出结果:
['d', 'l']

现在用函数实现该方法:

import random
def random_sample(list2, length):
    temp=[]
    for i in range(length*3):
        x=int(random.uniform(0,len(list2)))
        temp.append(list2[x])
    temp2= list(set(temp))
    temp2.sort(key=temp.index)
    return temp2[:length]

print(random_sample('string',3))
print(random_sample([1,2,3,4,5],3))
print(random_sample(range(10),3))
#输出结果:
['t', 'i', 'r']
[1, 3, 2]
[5, 9, 0]

2.用函数实现max方法:

#基础版:比较两个数的大小
def whoismax(a,b):
     if a>b:
         return a
     else:
         return b
f_num=int(input('please enter your num1:'))
l_num=int(input('please enter your num2:'))
result=whoismax(f_num,l_num)
print(str(result) +' is the max.')
#输出结果:
please enter your num1:4
please enter your num2:5
5 is the max.
#比较任意数字的大小:
  pass

3.实现判断两个字符串是否相等的方法

def whether_equal(string_1,string_2):
    if string_1==string_2:
        value='相等'
    else:
        value='不相等'
    return(value)
a=input('enter your string2:')
b=input('enter your string2:')
result=whether_equal(a,b)
print(result)
#输出结果:
enter your string2:we
enter your string2:we
相等
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值