函数

函数的定义

将经常要用到的代码封装称为函数,也就是可重复利用的代码块。

函数的创建与调用

定义函数,使用def关键字。

语法

def functionname(parameterlist):
    functionbody|pass|...
'''
parameterlist:可选参数,如果有多个使用逗号分隔
functionbody:函数体,函数被调用要执行的功能代码,如果定义一个什么也不做的函数,可以使用pass语句作为占位符
'''

案例

def filterchar(string):
    '''功能,过滤指定字符(如黑客)
    并将过滤后的结果输出,没有返回值
    '''
    import re
    pattern = r'(黑客)|(抓包)|(Trojan)'
    sub = re.sub(pattern,'****',string)
    print(sub)

#调用函数
about = '我是一名程序员,喜欢看黑客方面的图书,想研究一下Trojan。'
filterchar(about) #输出 我是一名程序员,喜欢看****方面的图书,想研究一下****。


参数传递

分为形式参数跟实际参数;

形式参数:相当于占位,用来接收实参传递的值(函数定义时,参数列表中的参数就是形参)
实际参数:真实传递的参数(函数调用时,传递进来的参数就是实参)

当实参为不变对象时(如字符串),进行的是值传递,改变形参的值,实参的值不变;
当实参为可变对象时(如列表),进行的是引用传递,改变形参的值,实参也发生改变;

案例

def demo(obj): #这里的参数就是形参,相当于占位
    print('原值:',obj)
    obj += obj

#调用函数
print('='*5,'值传递','='*5)
mot = 'python天下第一。'
print('函数调用前:',mot)
demo(mot) #这里的参数就是实参
print('函数调用后:',mot) #可以发现采用不可变对象字符串,改变了形参的值,实参没有发生变化

print('='*5,'引用传递','='*5)
list1 = ['赵飞','李萌','刘翔']
print('函数调用前:',list1)
demo(list1)
print('函数调用后:',list1) #可以发现采用可变对象列表,改变了形参的值,实参也发生了改变
'''
---------------脚本执行结果--------------------
===== 值传递 =====
函数调用前: python天下第一。
原值: python天下第一。
函数调用后: python天下第一。
===== 引用传递 =====
函数调用前: ['赵飞', '李萌', '刘翔']
原值: ['赵飞', '李萌', '刘翔']
函数调用后: ['赵飞', '李萌', '刘翔', '赵飞', '李萌', '刘翔']
'''

1、位置参数

位置参数也称为必备参数,调用时的数量位置必须和定义时是一样的。

案例

def person(name,age):
    print('{}的年龄是{}'.format(name,age))

#参数数量必须与定义的一致
person('赵飞',18)
person('赵飞',18,'喜欢馒头') #报错

#参数位置必须一致
person(18,'赵飞') #name取的时18,age取的是赵飞

2、关键字参数
在函数调用时使用形参的名字来确定输入参数的值,不需要与形参的位置一致,使调用函数传递参数更加灵活方便。

案例

def person(name,age):
    print('{}的年龄是{}'.format(name,age))
person(age=18,name='赵飞')

3、为参数设置默认值
当没有传入参数时,可直接使用定义函数时设置的默认值。
注意:在定义函数时,指定默认的形参必须在所有参数的最后。

案例

def add(a,b=10,c=4):
    print('和为:',a+b+c)

add(5,5) #此时的a=5 b=5 c=4
add(5,c=8) #此时的a=5 b=10 c=8
'''
可以看到,在没有指定参数c时,使用的是默认值c=4,参数是按顺序传入的
可以指定c=8,来指定传入的c参数为8
'''

4、可变参数
也称为不定长参数,即传入函数的实际参数可以是0个,一个,或任意个。
分为两种情况定义

第一种情况:
*parameter
表示能接收任意多个实际参数并放入一个元组中。

案例

def printgirl(*name):
    print('\n我喜欢的小姐姐有:')
    print(name) #打印接收参数
    for item in name:
        print(item)

printgirl('刘亦菲')
printgirl('刘亦菲','唐嫣','陈瑶')
'''
---------------脚本执行结果--------------------
我喜欢的小姐姐有:
('刘亦菲',)
刘亦菲

我喜欢的小姐姐有:
('刘亦菲', '唐嫣', '陈瑶')
刘亦菲
唐嫣
陈瑶
'''

案例
注意:如果包括位置参数,则需要定义在可变参数前。

def print_1(name,*args):
    print(name,'喜欢喝',args)
    print(name,'喜欢喝',*args)
print_1('飞飞','白开水','牛奶','奶茶')
'''
---------------脚本执行结果------------------
飞飞 喜欢喝 ('白开水', '牛奶', '奶茶')
飞飞 喜欢喝 白开水 牛奶 奶茶
'''

#如果要传入列表,则需要在实参前加**,表示将列表拆成元素,在装入元组中

def func1(name,*args):
    print(args) #输出('html', 'mysql', 'python')
    if len(args)>0:
        for i in args:
            print('{}学过了{}'.format(name,i))
    else:
        print('没有学过任何课程!')
courses = ['html','mysql','python']
func1('飞飞',*courses)
'''
---------------脚本执行结果--------------------
('html', 'mysql', 'python')
飞飞学过了html
飞飞学过了mysql
飞飞学过了python
'''

第二种情况:
**parameter
接收任意多个显式赋值的实际参数,并放入一个字典中。

案例

def func(**kwargs):
    print(kwargs)
func(a=1,b=2,c=3) #输出 {'a':1,'b':2,'c':3}
dict1={'001':'python','002':'java','003':'c语言'}
func(**dict1) #输出 {'001': 'python', '002': 'java', '003': 'c语言'}
'''
如果要传入字典,则需要在实参前加**,表示将字典拆成键值对,在装入形参成为字典
'''

#打印每位同学的姓名和年龄
students = {'001':('刘亦菲',18),'002':('景甜',19),'003':('唐嫣',20)}

def print_boy(who,**persons):
    print('{}喜欢的小姐姐是:'.format(who))
    if isinstance(persons,dict):
        for name,age in persons.values():
            print('{}同学的年龄是:{}'.format(name,age))
#调用
print_boy('我',**students)

返回值

在函数体内使用return语句为函数指定返回值,返回值可以是任意类型;
return语句一执行,就会结束函数,不在执行后续内容;
如果返回多个值,result中保存的是一个元组;

案例

def add(a,b):
    result = a+b
    return  '{}+{}={}'.format(a,b,result)
print(add(1,2)) #输出 1+2=3

#如果return跟多个值会放入元组中
def func1(a,b,c):
    return  a,b,c
print(func1(1,2,3))#输出 (1, 2, 3)

#也可以将多个值依次赋值
def func2(a,b,c):
    return  a,b,c
x,y,z=func2(1,2,3)
print(type(x)) #输出 <class 'int'>
print(x,y,z)#输出 1 2 3

函数的嵌套

函数可以互相嵌套使用;

案例

#定义生成验证码函数
import random
def generate_checkcode():
    l = '0123456789abcdefghijklmnopqrstyvwxyzABCDEFGHIJKLMNOPQRSTYVWXYZ'
    code = ''
    for i in range(5):
        ran =random.randint(0,len(l)-1)
        code += l[ran]
    return code

#定义用户登录函数
def login():
    username = input('输入用户名:')
    password = input('输入密码:')
    code =generate_checkcode() #调用生成验证码函数
    input_code=input('验证码为{}\n请输入你的验证码:'.format(code))
    if input_code.lower() == code.lower():
        if username == 'tz' and password == '123456':
            print('登录成功!')
        else:
            print('用户名或密码不正确!')
    else:
        print('验证码输入不正确!')

login() #调用函数

变量的作用域

变量的作用域指程序代码能够访问该变量的区域,如果超出该区域,访问就会报错。
分为局部变量全局变量

1、局部变量
函数内部定义,只在函数内部有效,可以在函数内部修改;

案例

#定义全局变量name
name = '小月月'
def func1():
    name = '小天才' #定义局部变量
    name += '会弹吉他'
    print(name) # 就近原则,先访问函数内部的name

def func2():
    name +='会弹琴' # 会报错,不允许修改全局变量
    print(name) 

2、全局变量

在函数外定义,函数内外部都能访问到。
不可变变量不能在函数内部修改,除非加上关键字global,申明为全局变量才能修改,如字符串;
在函数外部定义的可变变量可以在函数内部修改,无需加global,如列表等

案例

#定义全局变量name
name = '小月月'
def func1():
    name = '小天才' #定义局部变量
    name += '会弹吉他'
    print(name) # 就近原则,先访问函数内部的name

def func2():
    global name
    name +='会弹琴' 
    print(name) # 输出 小月月会弹琴

#可变变量修改不需要声明global
list1 = ['刘亦菲','章子怡','景甜']

def func1():
    print(list1)

def func2():
    list1.append('范冰冰')
    print(list1)

func2()
func1()
'''
可以看到未在函数内部声明global,先运行func2(),修改了可变变量列表;
在运行func1()可以看到全局变量list1已被修改
---------------脚本执行结果--------------------
['刘亦菲', '章子怡', '景甜', '范冰冰']
['刘亦菲', '章子怡', '景甜', '范冰冰']
'''

匿名函数

指没有名字的函数,通常只使用一次;使用lambda表达式创建匿名函数。

语法

result = lambda (arg1,arg2,...,argn):expression
'''
expression:必选参数,相当于函数体
'''

案例

#定义一个计算圆面积的函数
import math
def circlearea(r):
    result = math.pi*r*r
    return result
r = 10
print('半径为:',r,'的圆面积为:',circlearea(r))
#out: 半径为: 10 的圆面积为: 314.1592653589793

#使用匿名函数求圆面积
import math
r = 10
result = lambda r:math.pi*r*r #此时的result是一个lambda对象
print('半径为:',r,'的圆面积为:',result(r))
#out: 半径为: 10 的圆面积为: 314.1592653589793


案例集合

一些可以练手的例子

#定义一个产生范围1-20的随机数的函数
import random
def genrate_random(num):
    for i in range(num): 
        ran=random.randint(1,20) #随机数范围1-20
        print(ran)

num=input('请输入产生随机数的个数:')
genrate_random(int(num))

#写一个函数求列表中的最大值
#找最大值
def max_find(list1):
    big_num = 0
    for i in range(0,len(list1)-1):
        if big_num < list1[i]:
            big_num =list1[i]
    print(big_num)

list1=[2,3,8,58,2]
max_find(list1)

#找出最大值方法二
def max(iterable):
    max = iterable[0]
    for i in iterable:
        if i >max:
            max=i
    print('最大值是:',max)

list1 = [2,3,4,2,1]
max(list1)

#判断传入的参数是列表
def panduan(iterable):
    panduan = str(type(list1))
    if 'list' in panduan:
        print('这是一个列表')

list1 = [2,3,4,2,1]
panduan(list1)

#判断参数是否为列表方法二
#使用isinstance(变量,类型关键字)方法
def panduan(list1):
    if isinstance(list1,list):
        print('这是一个列表')
panduan(list1)

#验证3次输入账号密码
def yanzheng():
    i = 2
    while i>=0:
        username = input("请输入用户名:")
        password = input('请输入密码:')
        if username == 'tz' and password == '123':
            print('登录成功!')
            break
        else:
            print('账户或密码错误!你还可以输入',i,'次:')
            i-=1
yanzheng()

#使用可变参数*args定义一个求和函数
def sum(*args):
    sum = 0
    if len(args)>0:
        for i in args:
            sum+=i
    print('和为:',sum)

sum(1,2,3,4,5)#传入参数1,2,3,4,5
#输出 和为: 15


学习来自:《python从入门到项目实践》明日科技 第十一章

B站大学 P82-P96

posted @ 2020-11-17 11:08  努力吧阿团  阅读(86)  评论(0编辑  收藏  举报