python 函数相关(一)--参数、函数返回值、作用域、以及递归详细知识点

本篇博文详细讲述了函数的定义以及用法,以及一些典型的例子,对小白理解很有帮助,里面的内容和代码以及案例都是自己码的,程序一定要自己运行一下,理解弄懂就好了。
如有问题,欢迎大家批评指正!!!

1 函数

对于函数编程:

​ ● 本质:将 N 行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码,并执行。

​ ● 场景:

​ ● 代码重复执行

​ ● 代码量特别多,超过一屏,可以选择通过函数进行代码的分割

1.1 三元运算(三目运算)

三元函数是为了赋值的。前面的值 if 条件真 --> 前面的值 else 后面的值

if 条件 :
    v = 前面
else:
    v = 后面
    
v = 前面 if 条件 else 后面    # 一行就可以实现

1.2 函数的基本结构

# 函数的定义
def get_list_first_data():
    v = [11,22,['alex',666]]
    print(v[2])
# 函数的执行
get_list_first_data()   #['alex', 666]

练习

# 假如,管理员、业务员、老板用的是同一个邮箱。发送邮件的例子,输入管理员、业务员、老板显示发送成功
def send_email():
    print('邮件发送成功,假设有20行代码')

message = input('请输入角色:')
if message == '管理员':
    send_email()
if message == '业务员':
    send_email()
if message == '老板':
    send_email()

2 参数

2.1 基本参数知识

​ ● 任意个数

​ ● 任意类型

def func(a1,a2,a3):
    print(a1,a2,a3)
func(1,'alex',True)

​ ● 补充:对于函数的默认值慎用可变类型。

# 如果要想给 value 设置默认是空列表

# 不推荐(坑)
def func(data,value=[])
	pass

# 推荐
def func(data,value=None)
	if not value:
        value = []

举例:

def  func(a,b=[]):
    b.append(a)
    return b
# 分开打印
l1 = func(1)
print(l1)   # [1]
l2 = func(2,[11,22])
print(l2)  # [11,22,2]
l3 = func(3)
print(l3)  # [1,3]  
# 默认是同一个地址,如果不传参数,那么 b = [] 会随着添加进来的元素而改变。现在的 l1 变成了 [1,3]
# 如果有参数传入,则用自己传入的参数

问题:

​ ● def func(a,b=[]) 有什么陷阱?

​ b=[] 是可变类型,如果不传参数,默认是同一个地址。

​ ● 看代码写结果

def  func(a,b=[]):
    b.append(a)
    return b

l1 = func(1)  # [1]
l2 = func(2,[11,22]) # [11,22,2]
l3 = func(3)  # [1,3]
# 一起打印
print(l1,l2,l3)  # [1,3] [11,22,2] [1,3]


def  func(a,b=[]):
    b.append(a)
    return b
# 分开打印
l1 = func(1)
print(l1)   # [1]
l2 = func(2,[11,22])
print(l2)  # [11,22,2]
l3 = func(3)
print(l3)  # [1,3]

​ ● 看代码写结果

def  func(a,b=[]):
    b.append(a)
    print(b)

func(1)
# [1]
func(2,[11,22]) 
# [11,22,2]
func(3) 
# [1,3]

2.2 位置传参(调用函数,并传入参数)

def func(a1,a2):
    print(a1,a2)
func(1,'alex')  # 多一个或少一个都会报错

2.3 关键字传参 (位置可以打乱)

def func(a1,a2):
    print(a1,a2)
func(a2=1,a1=99)   # 顺序可以打乱

​ ● 关键字传参数和位置传参数可以混合使用 (位置传参一定在关键字传参前面)

def func(a1,a2,a3):
    print(a1,a2,a3)
func(1,2,a3=9)
func(1,a2=2,a3=9)
func(a1=1,2,9)  # 报错

​ ● 位置传参数在前 + 关键字传参数在后 = 参数总个数

​ ● 先处理位置传参,再处理关键字传参

2.4 默认参数【定义】

def func(a1,a2=9):  # 第二个位置的参数可传可不传,传--> 传的值,不传--> 默认9
    pass
func(1,2)  # 1 2
func(1,a2=18)  # 1 18
func(a1=123,a2=999)  # 123 999
func(12)  # 12 9

例子:

def func(a1,a2,a3=9,a4=10):  
    print(a1,a2,a3,a4)
func(1,2)  # 1 2 9 10
func(1,a2=18)  # 1 18 9 10
func(a1=123,a2=999)  # 123 999 9 10
func(1,2,a3=33,44)  # 报错  前面若有关键字传参,后面一定也是关键字传参,位置传参一定是在关键字传参前面
func(1,a2=2,a3=33,a4=44)  # 1 2 33 44
func(a1=1,a2=2,a3=33,a4=44)  # 1 2 33 44

2.5 万能参数

1.*args 是多个变量组成的元组,输出的类型都是元组

def func(*a):
    print(a)
    print(type(a))

func(1)   # (1,)  <class 'tuple'>
func(1,2)  # (1, 2) <class 'tuple'>
func((1,2,3,4,5))  # ((1,  2, 3, 4, 5),)  <class 'tuple'>
func('alex',1,True,[11,22,33],(1,2))  #  ('alex', 1, True, [11, 22, 33], (1, 2))  <class 'tuple'>
func(*(1,2,3,4,5))   # (1, 2, 3, 4, 5)  <class 'tuple'>
func(*('alex',1,True,[11,22,33],(1,2)))   # ('alex', 1, True, [11, 22, 33], (1, 2))  <class 'tuple'>

​ ● *args 只支持位置传参,不支持关键字传参

​ ● 可以接受任意个数的参数,并将参数转换成元组

​ ● 调用函数有 *

def func(a1,*args):
    print(a1,args)
func(1,2,3,4,5)  # 1 (2, 3, 4, 5)

def func(a1,*args,a2):
    print(a1,args,a2)
func(1,2,3,4,5)  # 1 (2, 3, 4, 5)  只要a2 前面有args,a2永远拿不到值

def func(a1,*args,a2=10):
    print(a1,args,a2)
func(1,2,3,4,5)  # 1 (2, 3, 4, 5) 10

def func(a1=10,*args,a2=10):
    print(a1,args,a2)
func(1,2,3,4,5)  # 1 (2, 3, 4, 5) 10  1 把a1 = 10 覆盖了

​ ● 调用函数无 *

def func(a1,a2=9): 
	pass
func(1,2)  # 1 2

​ ● 只能用位置传参

2.**kwargs 关键词传参:输出类型是字典

def func(**kwargs):
    print(kwargs)

​ ● **kwargs 只支持关键字传参

​ ● 可以接受任意个数的关键字参数,并将参数转换成字典

​ ● 调用函数有 **

func(**{'k1': 1, 'k2': 'alex'})  # {'k1': 1, 'k2': 'alex'}

​ ● 调用函数无 **

func(k1=1,k2='alex')  # {'k1': 1, 'k2': 'alex'}

3.综合应用

def func(*args,**kwargs):
    print(args,kwargs)

func(1,2,(1,2),k1=1,k2='alex')  #  (1, 2, (1, 2)) {'k1': 1, 'k2': 'alex'}

3 函数的返回值

def func():
    pass  # 无返回值,默认None

def bar():
    return 9  # 有返回值,返回9

3.1 return 用法

# 有返回+可修改数据
v = [11,22,33,44]
result = v.pop()
print(result)
print(v)

# 仅有返回值
v = 'alex'
result = v.split('l')
print(result)  # ['a', 'ex']  有返回值

v = {'k1':'v1','k2':'v2'}
result1 = v.get('k1')  # v1
result2 = v.keys()  # dict_keys(['k1', 'k2'])
print(result1,type(result2))

# 无返回值
v = [11,22,33,44]
v.append(99)  # 无返回值

3.2 练习题

练习1 发送邮箱

# 邮箱  无返回值
def send_email(role,to):
    template = '要给%s%s发送邮件'%(role,to,)
    print(template)

message = input('请输入角色:')
if message == '管理员':
    send_email('管理员','jdhsifs@qq.com')  # 要给管理员jdhsifs@qq.com发送邮件
if message == '业务员':
    send_email('业务员','4363657856@qq.com')
if message == '老板':
    send_email('老板','jgdftgdr45s@qq.com')

val = send_email('管理员','jdhsifs@qq.com')  # 调用返回值
print(val)  # None    若有return,有返回值,否则,为None


# 邮箱  有返回值
def send_email(role,to):
    template = '要给%s%s发送邮件'%(role,to,)
    print(template)
    return '结束'

message = input('请输入角色:')
if message == '管理员':
    val = send_email('管理员','jdhsifs@qq.com')  # 要给管理员jdhsifs@qq.com发送邮件    # 调用返回值
if message == '业务员':
    val = send_email('业务员','4363657856@qq.com')  # 调用返回值
if message == '老板':
    val = send_email('老板','jgdftgdr45s@qq.com')  # 调用返回值


print(val)  # 结束    若有return,有返回值,否则,为None

练习2 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个’你好’

# 方法一
def count_num(arg):
    count = 0
    for i in arg:
        if i == 'A':
            count += 1
    return count

content = input('请输入:')  # hhhhhhhdfAAAAAAAAAAAFSDZG
val = count_num(content)
print(val)  # 11
val = int(val)
f = open('a.txt',mode = 'w',encoding = 'utf-8')
for i in range(0,val):  # 前取后不取   等价于for i in range(val):
    f.write('你好')
f.close()

# 方法二
def count_num(arg):
    count = 0
    for i in arg:
        if i == 'A':
            count += 1
    return count
def write_file(line):
    if line == 0:
        return False  # 函数执行过程中,一旦遇到return,则停止函数的执行
    f = open('a.txt', mode='w', encoding='utf-8')
    f.write(content)
    f.close()
    return True
message = input('请输入:')  # hhhAAhhhAAhdfAFSDZGAA
val = count_num(message)
print(val)  # 7
content = '你好'* val
write_file(content)
status = count_num(message)
if status:
    print('写入成功')
else:
    print('写入失败')

练习3 写函数,计算一个列表中有多少个数字,打印:列表中有%s个数字。

​ 提示:type(‘x’) == int 判断是否是数字。

# 方法一:
def num_count(list):
    count = 0
    for item in list:
        if type(item) == int:
            count += 1
    return count

num_count(['gf',1,55,7,'fggh'])
num = num_count(['gf',1,5,7,'fggh'])
message = '列表中有%s个数字'%(num,)
print(message)

# 方法二:
def num_count(list):
    count = 0
    for item in list:
        if type(item) == int:
            count += 1
    message = '列表中有%s个数字' % (count,)
    print(message)

num_count(['gf',1,55,7,'fggh'])

练习4 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。【注】题目没说要打印,因此不需要print()

# 方法一:
def new_list(list):
    new_list = list[::2]
    return new_list

new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])

# 方法二:
def new_list(list):
    new_list =[]
    list_len = len(list)
    for i in range(0,list_len):
        if i % 2 == 0:
            new_list.append(list[i])
    return new_list

new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])
# v = new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh'])
# print(v)

练习5 阅读文件,将文件的内容构造成指定格式的数据,并返回,打印出来。

'''
a.log文件
     alex|123|18
     eric|uiuf|19
     ...
目标结构:
a. ['alex|123|18','eric|uiuf|19'] 并返回
b. [['alex','123','18'],['eric','uiuf','19']] 并返回
c. [
     {'name':'alex','pwd':'123','age':'18'}
     {'name':'eric','pwd':'uiuf','age':'19'}
]
...
'''
def write_file():
    file_w = open('a.log',mode = 'w',encoding = 'utf-8')
    content = 'alex|123|18\n'+'eric|uiuf|19\n'
    file_w.write(content)
    file_w.close()

def list_str():
    file_r = open('a.log', mode='r', encoding='utf-8')
    a = []
    for line in file_r:
        line = line.strip()
        a.append(line)
    print(a)  # 如果下面有print,此处就不用写了,如果下面没有print,此处就写
    file_r.close()
    return a

def list_list():
    file_r = open('a.log', mode='r', encoding='utf-8')
    b = []
    for line in file_r:
        line = line.strip()
        result = line.split('|')
        b.append(result)
    print(b)  # 如果下面有print,此处就不用写了,如果下面没有print,此处就写
    file_r.close()
    return b

def list_dict(iii):
    file_r = open('a.log', mode='r', encoding='utf-8')
    a = []
    b = []
    c = []

    for line in file_r:
        line = line.strip()
        a.append(line)

        result = line.split('|')
        b.append(result)

    file_r.close()
    for i in range(0,2):
        info = {}
        info['name'] = b[i][0]
        info['pwd'] = b[i][1]
        info['age'] = b[i][2]
        # print(info)
        info.update(info)
        c.append(info)
      # 如果下面有print,此处就不用写了,如果下面没有print,此处就写
    if iii == 'a':
        print(a)
    elif iii == 'b':
        print(b)
    elif iii == 'c':
        print(c)
    return a,b,c
# list_str()
# list_list()
list_dict('a')
list_dict('b')
list_dict('c')

4 作用域

1.python 中:

​ ● py文件:全局作用域 全局变量以后必须要大写

​ ● 函数:局部作用域

a = 1   # 全局变量

def s1():  # 局部变量
    x1 = 666
    print(a)  # 1
    print(b)  # 2
    print(x1)  # 666

b = 2
print(a) # 1
s1()  # 若s1 放在b的前面,报错
a = 888
def s2():
    print(a,b)   # 888 2
    s1()  # s2()函数内部调用另一个函数 s1()的前提是,s1()在全局上有定义

s2()
c = a + b
print(c)
######## 执行顺序:a = 1--> b = 2--> print(a)--> s1()  [print(a)-> print(b) ->print(x1)] --> s2() print(a,b) --> c = a + b -->print(c)

2.函数的嵌套

# 函数的嵌套
x = 10
def func1():
    x=9
    print(x)
    def func2():
        x=999
        print(x)
    print(x)
    func2()
func1()  # 先执行func1()  9 --> print(x)   9 -->func2()   999


x = 10
def func1():
    x=8
    print(x)
    def func2():
        print(x)

    func2()
    x = 9
    func2()
    x = 10
    print(x)
func1()  # 8-->8--> 9--> 10



name = 'oldboy'
def func():
    name = 'alex'  # 在自己作用域再创建一个这样的值,无法覆盖父级的值
    print(name)  # alex
func()
print(name)  # oldboy


name = [11,2,33,11]
def func():
    name.append('alex')  #  不是重新赋值,但是可以对可变类型【列表、字典】修改
    print(name)   # [11, 2, 33, 11, 'alex']
func()
print(name)  # [11, 2, 33, 11, 'alex']

3.global 如果非要对全局变量进行重新赋值,即使函数有嵌套,也是对全局变量修改

# 情况一:
name = 'oldboy'
def func():
    global name
    name = 'alex'
    print(name)  # alex
func()
print(name)  # alex

# 情况二:
name = 'oldboy'
def func():
    name = 'alex'
    print(name)  # alex
    def inner():
        global name
        name = 999
    inner()
func()
print(name)  # 999

4.nonlocal 找到上一级进行修改

name = 'oldboy'
def func():
    name = 'alex'
    def inner():
        nonlocal name
        name = 999
    inner()
    print(name)  #  999
func()
print(name)  # oldboy

5.总结:

​ ● 一个函数是一个作用域

​ ● 作用域中查找数据规则:优先在自己的作用域查找,自己没有就去“父级”–> 下一级“父级” --> 直到全局。全部没有就报错。

​ ● 局部可以用全局的,全局不能用局部的

5 递归

​ ● 本质:函数自己调用自己,效率不高。【默认递归次数是1000次】

def func():
    print(1)
    func()
func()  # 不停的循环打印 1 ,最多打印 1000 次
def func(i):
    print(i)
    func(i+1)
func(1)  # 打印 1 2 3 4 ...
def func(a,b):
    print(b)
    func(b,a+b)
func(0,1)  # 1 1 2 3 5 8 13 21 ...

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值