python函数详解

一、函数基础 上

1.1 函数简介 function

input(),print(),range()函数等等

现在的代码可复用性非常差

函数是干嘛的?就是存数据的

总结我们函数的优点:
1.遇到重复功能的时候,直接调用就可以,减少代码量
2.提升代码,项目的结构性,分工明确,提高代码的可读性
3.遇到扩展功能时,修改比较方便

自定义函数,将一段有规律的、可重复使用的代码定义成函数,一次编写,多次调用

n = 0
for i in 'https://www.baidu.com/':
    n += 1
print(n)

print(len('https://www.baidu.com/'))

函数的本质就是一段有特定功能、可以重复使用的代码

这段代码已经被提前编写好了,并且起了一个好听的名字

def my_len(str):
    lenght = 0
    for c in str:
        lenght += 1
    return lenght

lenght = my_len('https://www.baidu.com/')
print(lenght)

1.2 函数的定义

定义函数

def 函数名(形参1,形参2,形参n):
	代码块

1.3 函数的调用

语法: 函数名()
要先创建,在调用
def fn():
    print('这是我的第一个函数')
    print('hello')
    print('吃了吗')
    print('再见')
fn()

注意:
fn			是什么  函数对象
fn()		是什么  调用函数
print		是什么  函数对象
print()		是什么  调用函数

练习:
定义一个login函数,功能是输入用户名和密码,验证是否正确

def login():
    username = input('用户名:')
    password = input('密码:')
    if username == 'root' and password == '123':
        print('登陆成功')
    else:
        print('登陆失败')

login()

1.4函数的参数

1.4.1 形参和实参

参数可以分为有参和无参

什么是无参?就是在定义函数时,括号里面没有东西就是无参

有参指的就是括号里面有参数

定义函数一般都是需要实现某种功能的

定义一个函数,可以用来求任意两个数的和

def sum():
    print(1+1)
sum()

def sum():
    a = 66
    b = 99
    print(a+b)
sum()

函数的参数:在定义函数时,可以再函数名后()中定义数量不等的形参,注意 :可以有也可以没有,可以有一个也可以有很多个,多个形参之间我们使用逗号隔开

什么叫形参? 形式参数,定义形参就相当于在函数内部声明了变量,但是没有赋值

实参:实际参数,在函数定义时制定了形参,在调用的时候必须传递实参,实参会赋值给对应的形参,有几个形参就必须传递几个实参

fn(a,b):
    print('a=',a)
    print('b=',b)
fn(666,888)

def sum(a,b):
    print(a,'+',b,'=',a+b)
sum(5.5,1.4)
总结:我们在定义函数的时候叫形参,为什么叫形参,因为那个参数是形式的,并没有值,需要调用的时候才可以确定值
调用的时候叫实参
注意:定义了多少个形参就要传递多少个实参

1.4.2 参数的传递方式

参数呢他在传递的时候也是有不同的方式,在形参中,有我们的一个默认值参数

def fn(a,b,c=10):
    print('a=',a)
    print('b=',b)
    print('c=',c)
fn(1,2)

1.4.3 位置参数和关键字参数

1.位置参数就是将对应位置的实参赋值给对应位置的形参
def ms(年龄,姓名,手机号,qq号,微信号,国家,父亲名字,省份,母亲名字)
	pass
ms()
2.关键字参数:可以不按照形参定义的顺序来传递,而是直接会根据参数名来传递参数
def fn(a,b,c):
    print('a=',a)
    print('b=',b)
    print('c=',c)
fn(a=2,c=3,b=2)
好处是什么:不需要记忆我们参数的一个顺序,只需要记住名字就可以了
位置参数和关键字参数可以混合使用
混合使用关键字和位置参数时,位置参数必须在关键字参数的前面

2.4.4实参的类型

函数在调用的时候不会限制你的类型,实参可以传递任意类型

def fn(a):
    print('a=',a)
b = [True]
b = fn
fn(b)

a= <function fn at 0x000002880C7385E0>

实参可以是任意一个类型,什么都行

二、函数基础下

2.1 函数参数

2.1.1 * args

定义函数时,可以再形参的前面加一个 * 号,我们的形参就能获得我们所有实参。这个 * 代表所有的意思 他会将我们所有的实参保存到一个元组当中

def fn(*a):
    print(a)
    print(type(a))
fn(1,2,3,4,5)

(1, 2, 3, 4, 5)
<class 'tuple'>

*a能接受所有的实参,并且将实参保存到一个元祖中
装包,我们把这些散开的数据,转到一个元祖中,这就叫装包
好处就是相传几个就是几个,不传也可以
def sum(*a):
    result = 0 #初始化
    for i in a:
        result += i  #result = result + i
    print(result)
sum(1,2,3,4,5,6,7,8,9)

45
#带*号的形参只有一个,因为你写多了就没法分值
#带*号的参数可以和其他参数配合使用,但是得写在最后面

def fn(a,b,*c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
fn(1,2,3,4,5,6,7,8,9,10)

def fn(*a,b,c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
fn(1,2,3,4,5,6,7,8,b=9,c=10)

a= 1
b= 2
c= (3, 4, 5, 6, 7, 8, 9, 10)

a= (1, 2, 3, 4, 5, 6, 7, 8)
b= 9
c= 10

使用带 * 号的参数一般取名为args

*args弊端就是只能接受位置参数

2.1.2 * * kwargs
def fn(**args):
    print('args=',args)
    print(type(args))
fn(a=1,b=2,c=3)

args= {'a': 1, 'b': 2, 'c': 3}
<class 'dict'>
总结:
**形参可以接收任意的关键字参数,会将这些参数统一保存到字典当中,字典的键就是参数的名字,字典的值就是参数的值,所以现在这个键a值是1,b值是2,c值是3
注意:**形参也是只能有一个,并且必须写在所有参数最后,他必须得是最后一个,他的命名潜规则是kwargs
2.1.3 同时使用不定长参数

**当要同时使用 * args和 * *kwargs的时候, * args是必须写在 * *kwargs的前面,这是规定

def fn(a,b,*args,**kwargs):
    print(a)
    print(b)
    print(args)
    print(kwargs)
fn(1,2,3,4,5,6,1,6,3,k=1,ww=3,c=5)

1
2
(3, 4, 5, 6, 1, 6, 3)
{'k': 1, 'ww': 3, 'c': 5}
2.1.4 参数的解包
def fn(a,b,c,d,e,f):
    print('a=', a)
    print('b=', b)
    print('c=', c)
    print('d=', d)
    print('e=', e)
    print('f=', f)
t = (1,2,3,4,5,6)
# fn(t[0],t[1],t[2])
fn(*t)

a= 1
b= 2
c= 3
d= 4
e= 5
f= 6

传递实参时,也可以在序列类型的参数前面添加 * 号,这样会自动将序列中的元素依次作为参数传递
注意:序列中的元素的个数必须和我们函数形参的个数一致
    
    def fn(a,b,c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
# fn(*[1,2,3]) # 列表也行
fn(*[1,2,3,4]) # 报错, 序列元素和形参必须一致

a= 1
b= 2
c= 3

def fn(a,b,c):
    print('a=', a)
    print('b=', b)
    print('c=', c)
    
d = {'a':10, 'b':20, 'c':30}
fn(**d)
总结:
1.*args适用于接收多个未命名的位置参数,**kwargs用于接收关键字参数,其中args是一个元组类型,而kwargs是一个字典类型的数据
2.*args也就是把元组中的数据拆分成单个的数据
**kwargs吧字典中的数据拆分成单个的键值对

2.2 函数的返回值

返回值就是函数执行以后返回的结果

f(x) = 2x+1

x=1 ==>3 f(1)=3

x=2 ==>5 f(2)=5

def fn():
    return [1,2,3,4]
# 获取返回值我们的方式是  把函数调用当做一个值来输出
x = fn()
print(x)
print(fn())

return后面是什么, 返回的结果就是什么
return后面可以是任意的值,包括函数,跟什么就返回什么
无论定义的是返回什么类型,return只能返回单个值,但是值可以有多个元素

def fn1():
    return [1,3,5]
print(fn1())
print(type(fn1()))

def fn2():
    return ('1,3,5')
print(fn2())
print(type(fn2()))

(1, 3, 5)
<class 'tuple'>
[1, 3, 5]
<class 'list'>
1,3,5
<class 'str'>
def fn():
    def fn2():
        print('hello')
    return fn2
r = fn()
print(r)
r()

<function fn.<locals>.fn2 at 0x00000175C0F389D0>
hello

None是python一个特别空值,用来代表空的

def fn():
    pass
print(fn())  # None ==> 空值,不可以理解为0
print(type(None))

None
<class 'NoneType'>
如果不给一个函数返回值,那么他的返回值就是空的None
只要函数不带return,那么返回的是None

def fn():
    return
print(fn())

总结:如果仅仅写一个return或者不写return,就等价于return None
None是python一个特别空值,用来代表空的
def fn():
    print('抄一遍')
    print('抄两遍')
    print('抄三遍')
    return
    print('抄四遍')
fn()

抄一遍
抄两遍
抄三遍

在函数中,return代表函数执行结束
def fn():
    for i in range(1,101):
        if i == 66:
            print('分手心痛了,提前结束')
            #break
            return
        print(f'抄{i}遍')
fn()
break:退出当前循环
continue;跳过本次循环,但是对于后面没有影响
return:用来结束函数
def sum(*args):
    result = 0
    for i in args:
        result += i
    return result
r = sum(1,2,3,4)
print(r+10)

print(print())

a = len('hello')
print(a)

fn()和fn的区别:
fn==》函数对象,打印它其实就是在打印函数对象
fn()==》调用函数,打印fn()其实就是在打印fn()的返回值
总结;
return语句的作用
结束函数调用,返回值
函数体中return语句有指定的返回值 时  返回的是  其值
函数体中没有return语句,函数运行结束会隐含返回一个None作为返回值,类型是Nonetype,与return,returnNone等效,都是返回None

printreturn
print仅仅是打印在控制台上,而return则是将return后面的部分作为返回值,作为函数的输出,可以用来变量接收,继续使用这个返回值做其他事

三、匿名函数和递归函数

3.1 匿名函数 lambda

lambda 参数列表:运算表达式
def fn(x):
    return x*x
print(fn(5))
f = lambda x:x*x
print(f(5))
总结:
1.lambda并不会带来程序运行效率的提高,只会使代码更加的简洁
2.如果使用lambdalambda内不要有循环,因为可读性不好,有的话请使用标准函数来完成,目的是为了代码有可重用性和可读性
3.lambda只是为了减少单行函数的定义而存在,如果一个函数只有一个返回值,只有一句代码,就可以使用lambda

3.2 高阶函数

3.2.1 简介

高阶函数其实就是把函数作为参数传入

就是把一个函数作为另一个函数的参数传入

abs()==》完成对数字绝对值计算

print(abs(-5))

sum()==》求和

sum(可迭代对象,指定一个相加的参数如果没有默认为0)
print(sum([1,2,3,4,5]))
print(sum((1,2,3,4,5),1))

round()==》四舍五入

print(round(4.3))
print(round(4.8))

print(round(4.5))  # 4 坑

https://www.cnblogs.com/bigc008/p/9682105.html

任意两个数字,对两个数字求绝对值后进行求和

def ab_sum(a,b,f):
    return f(a)+f(b)
res = ab_sum(-1,-4,abs) #把abs作为参数传入到函数里面,传的是函数本身不是传函数调用
print(res)
def xfs(x):
    return -x

def ab_sum(a,b,f): # f是一个函数参数
    return f(a)+f(b)
res = ab_sum(-1,-4,xfs)  # 求的是相反数的和
print(res)

函数作为参数的函数

函数三剑客:map , reduce filter

3.2.2 map()
map(func,seq)第一个参数是给一个函数,第二个是给一个序列类型

将列表序列中各个元素加一

# 普通写法
list1 = [1,2,3,4,5]
list2 = []
for i in list1:
    list2.append(i+1)
print(list2)
#map用法
list1 = [1,2,3,4,5]
print(list(map(abs,list1)))
list1 = [1,2,3,4,5]
def add1(x):
    return x+1
print(list(map(add1,list1)))

[2, 3, 4, 5, 6]
list1 = [1,2,3,4,5]
print(list(map(lambda x:x+1,list1)))
总结:
1.map内置函数的作用是操作序列中的所有元素,并返回一个迭代器,迭代器要转列表才能得到最终的值
2.我们的lambda表达式可以专门配合我们的高阶内置函数来做简单实现
3.2.3 reduce
reduce(func,seq)将每次函数计算的结果继续和序列的下一个元素做累积计算,最终结果只有一个值

注意:reduce传入的参数func必须接受两个参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VjGO3mhH-1689409273495)(C:\Users\18361\AppData\Roaming\Typora\typora-user-images\image-20220929212315534.png)]

计算列表中各个数字的和

list1 = [1,2,3,4,5]
sum = 0
for i in list1:
    sum += i
print(sum)

list1 = [1,2,3,4,5]
def f(a,b):
    #print('进入f')
    #print('a=',a)
    #print('b=',b)
    return a+b
res = reduce(f,list1)
print(res)

3.2.4 filter()==》过滤

filter(func,seq)结果可以通过list转换

保留一个序列中所有偶数

list1 = [1,2,3,4,5,6,7,8,9,10]
for i in list1:
     if i %2 != 0:
         list1.remove(i)
print(list1)
list1 = [1,2,3,4,5,6,7,8,9,10]
def os(x):
    return x%2 == 0
print(list(filter(os,list1)))

print(list(filter(lambda x:x%2==0,list1)))
3.2.5 sorted
list1 = [2,4,1,3,5,6,9,7]
print(sorted(list1))  # 升序
print(sorted(list1,reverse=True))  # reverse=True 是反转的意思
list1 = ['天天:69','二则:78','涛婆:89','广广:100','左手:95']
print(sorted(list1))
def f(x):
    arr = x.split(':')
    return int(arr[1])
print(sorted(list1,key=f))


print(sorted(list1,key=lambda x:int(x.split(':')[1])))

3.3 递归函数

有可能搞得我们内存崩溃

如果一个函数的内部调用了自己,就叫递归

内存溢出

1.如果要定义递归函数,不想让他报错的话,必须要有出口

2.不断的向出口接近

打印1到500

x = 1
def func():
    global x
    if x == 500:
        print(x)
    else:
        print(x)
        x += 1
        return func()
func()
def func(1):
    if x == 501:
        return
    print(x)  
    return func(x+1)
func(1)
9=  9*8*7*6*5*4*3*2*1
9=  9*89=  9*8*7
def f(n):
    if n == 1:
        return True
    return n*f(n-1)
a = f(9)
print(a)
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二价亚铁.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值