python基础⑥-函数

本文详细介绍了Python的基础函数概念,包括函数的定义、参数类型(无参、有参、默认参数、不定长参数)、关键字参数、匿名函数(lambda)以及装饰器的使用。通过实例展示了如何在函数中传递不同类型的参数,并探讨了闭包和装饰器在代码复用和功能增强上的作用。此外,还强调了装饰器在遵循开放封闭原则下的重要性。
摘要由CSDN通过智能技术生成

系列文章目录


python基础①-基础环境搭建和工具使用
python基础②-常用的各种数据类型初认知
python基础③-数据类型常用的操作和方法字符串、数值、bool
python基础④-数据类型常用的操作和方法列表、元组、字典、集合
python基础⑤-控制流程
python基础⑥-函数
python基础⑦-字符编码与文件操作
python基础⑧-异常
python基础⑨-迭代器和生成器
python基础⑩-面向对象
python基础⑪-继承与派生
python基础⑫-多进程
python基础⑬-多线程
python基础⑭-进程池、线程池、协程
python基础⑮-网络编程socket
python基础⑯-网络编程socket进阶

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。—摘抄https://www.runoob.com/python/python-functions.html

函数基础

# 函数的三大特性
# 功能,参数,返回值
#### 有代码(有功能)
def factory():   #  制造一个工厂
	print('正在制造手机')  # 代码相对于员工或者机器
factory()
#### 无代码(有时候代码还没来得及写。但是有知道这段代码该做什么可以先定义好函数)
def shopping():
	pass
shopping()

在这里插入图片描述

函数各种参数

无参函数


# 参数
# 无参函数
# 应用场景仅仅只是执行一些操作,比如与用户交互,打印(工厂制造手机,不需要外接资源)
def factory():   #  制造一个工厂
 print('正在制造手机')  # 代码相对于员工或者机器
factory()

在这里插入图片描述

有参函数


# 有参
# 需要根据外部传进来的参数,才能执行相应的逻辑,计算 (工厂制造手机,需要a零件和b零件)
def factory(a,b):   #  制造一个工厂
    # 1 形参: 指的是在定义函数阶段括号内指定变量名,即形参本质就是"变量名"
    #  形参可以看做一个变量名
    print('a是%s'%a)
    print('b是%s'%b)
factory('小明','小王')

在这里插入图片描述

实参

指的是在调用函数阶段括号内传入的值,即实参本质就是"值"
调用函数的参数称为实参
形参与实参的关系:在调用函数时,会将实参(值)赋值(绑定)给形参(变量名)

位置传参
factory(3,2)
# 注意:但凡按照位置定义的形参,必须被实参传值,多一个不行,少一个也不行
# 位置参数 *****
# 错误示范
# factory(1,2,3)
# # factory(1)

在这里插入图片描述

关键字传参
#关键字实参: 
# 在调用函数阶段,按照key=value的形式指名道姓地为形参传值
#注意:
#1. 可以完全打乱顺序,但仍然能指名道姓为指定的形参传值
#2. 可以混合使用位置实参与关键字实参,但是必须注意:
#    2.1 位置实参必须放到关键字实参前面
#    2.2 不能对一个形参重复赋值
factory(b=1,a=2)
# 错误示范
# factory(a =1 ,a=2,b=2)
# factory(1,a=1,b=2)
# factory(a=2,2)
# 正确
factory(2,b=2)

在这里插入图片描述

默认参数


#默认参数  
#默认参数:指的是在定义函数阶段,就已经为某个形参赋值了,改形参称之为有默认值的形参,简称默认形参
#注意:
#1. 在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值
#2. 位置形参应该放到默认形参前面
#3. 默认参数的值在函数定义阶段就已经固定死了
def factory(a,b=2):#  在定义阶段就已经被赋值,意味着在调用可以不用为其赋值,也可以对其重新赋值
    c = a + b
    print(c)

factory(1,5)

# 位置形参vs默认形参
# 对于大多情况下传的值都不相同的,应该定义成位置形参
# 对于大多情况下传的值都相同的,应该定义成默认形参

def register(name,age,sex='男'):
    print(name,age,sex)

register('小王',18)
register('小戴',18,'女')
register('小王',18)
register('小王',18)
register('小王',18)

在这里插入图片描述

不定长参数

带*参数

可变长度的参数(不定长参数)
在形参中带*:会将调用函数时溢出位置实参保存成元组的形式,然后赋值*后的变量名


def foo(x,y,*z):
    print(x,y,z)
    print(*z)
foo(1,2,3,4,5,6)

# 实参打散
foo(1,*(2,3))
foo(*(1,2,3))
foo(*[1,2,3])
foo(*'abc')

在这里插入图片描述

带**参数

在形参中带**:会将调用函数时溢出关键字实参保存成字典的形式,然后赋值**后的变量名

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

foo(1,2,a=1,b=2,c=3)
foo(1,y=1,a=1,b=2,c=3)

在这里插入图片描述

** 与* 混合使用

规范: 在形参中带*与**的,*后的变量名应该为args,**后跟的变量名应该时kwargs

def factory(*args,**kwargs):# * 接受的是0个到多个位置参数
    # ** 接受的是0个到多个关键字参数
    print(args)
    print(kwargs)
factory(1,2,3,x=3,y=4)
factory(*[1,2,3],**{'x':3,'y':4})

在这里插入图片描述

*加在 列表、元组、集合、字典前可以打散元素
**加在字典前可以打散字典成为关键字参数

print(*(1,2,3))
print(*[1,2,3])
print(*{1,2,3})
print(*{'name':'小王','age':18})
# **{'name':'小王','age':18} 

在这里插入图片描述

函数包装

# !!!!!!!!!!!!!!!当我们想要将传给一个函数的参数格式原方不动地转嫁给其内部的一个函数,
# 应该使用下面这种形式

def bar(x,y,z):
    print(x,y,z)
    
def wrapper(*args,**kwargs):
    bar(*args,**kwargs)
    
wrapper(1,2,3)

# 虽然调用的是wrapper,但是要遵循的确是bar定义的参数标准

在这里插入图片描述

多种参数混合

# 了解
# 命名关键字参数: 放到*与**之间的参数称之为命名关键字参数 ***
def foo(x,y,*args,m,n,**kwargs):
    print(x,y) # 1 2
    print(args) # (3, 4, 5, 6)放到元组
    print(m,n) # 3 4
    print(kwargs) # {'a': 1, 'b': 2, 'c': 3}
# # 错误
#foo(1,2,3,4,5,6,a=1,b=2,c=3)
# 正确
foo(1,2,3,4,5,6,m=3,n=4,a=1,b=2,c=3)

在这里插入图片描述

匿名函数

匿名函数:就是没有名字的函数
为何要用:
用于仅仅临时使用一次的场景,没有重复使用的需求
匿名函数,除了没有名字其他的都有
语法 lambda空格+参数+冒号+函数体代码(表达式或者函数)
一行代码图省事
像java中的lambda表达式

基本用法


# # 匿名函数的定义
print(lambda x,y:x+y)
# # 调用直接内存地址加括号(它虽然没有名字)+括号可以调用
# 返回值省去了return
# 表达式
print((lambda x,y:x+y)(1,2))
# # 函数
print((lambda x,y:print(x+y))(1,2))

在这里插入图片描述

巧妙利用匿名函数(简洁、美观、易懂)

对比两种取字典中最大值的方法。匿名函数非常的方便

# # 把内存地址赋值给一个变量没有意义
# # 匿名函数的精髓就是没有名字,为其绑定名字是没有意义的
#f=lambda x,y:x+y
#print(f(1, 2))
# 匿名函数与内置函数结合使用
# max,min,sorted
salaries = {
    'xiaowang':3000000,
    'xiaodai':10000,
    'xiaozhou':3000
}
# # 求薪资最高的那个人名:即比较的是value,但取结果是key
# # 默认比较key值
print(max(salaries))
# # max(字典,key=函数名)
def func(name):
    return salaries[name]
print(max(salaries, key=func))

# # 在外面我们不要用它
# # func(1)
# # 求最大值即比较的是value工资,但取结果是key人名
print(max(salaries, key=lambda name: salaries[name]))
#
# # 求最小值
print(min(salaries, key=lambda name:salaries[name]))
# sorted排序

在这里插入图片描述

nums = [11,33,22,9,1]
res = sorted(nums,reverse=True)
print(res)

# 循环遍历薪资
for v in salaries.values():
    print(v)

print(sorted(salaries.values()))
# 但是我们是要比较薪资,返回的却是人名
# 薪资反序
print(sorted(salaries, key=lambda name: salaries[name], reverse=True))
# 薪资正序
print(sorted(salaries, key=lambda name: salaries[name], reverse=False))

在这里插入图片描述

闭包函数

基本用法

闭包函数
闭指的是:该函数是一个内部函数
包指的是:指的是该内部的函数名字在外部被引用
即调用一个函数,返回的结果是另一个函数还能在调用

# 1、函数定义阶段:
# 只检测函数体的语法( 工厂合不合格),不执行函数体代码 (不使用工厂)
#def factory():#  制造一个工厂
    print('正在制造手机') # 代码相对于员工或者机器

# 2、函数调用阶段:
# 1 先找到名字   (找到工厂的位置)
# # 2 根据名字调用代码   ( 加了括号执行工厂进行加工)
#
#factory()

def outer():# 没有调用outer()
    #1 只检测函数体outer的语法( 工厂合不合格),不执行函数体代码 (不使用工厂)
    print('外面的函数正在运行')
    def inner():
        print('里面的函数正在运行')
    return inner # 3返回inner函数的内存地址  想象成一个钥匙 控制里面工厂
# 4 得到里面工厂的钥匙 钥匙取一个名字inner
inner=outer() #2 定义了inner函数# 是不是直接函数名加括号就可以调用呢?
# 5 里面钥匙加括号就可以开启里面的工厂
inner()

在这里插入图片描述

闭包传参

# 为函数体传值的方式一:参数
def func(x,y):
    print(x+y)

func(1,2)
func(1,2)


# 为函数体传值的方式二:闭包
def outer(x,y):

    def func():
        print(x + y)
    return func
#
# print(outer(1,2))
func=outer(1,2)
# print(func)
# 不用再次写参数可以达到传入1,2
func()
func()

闭包函数可以将参数封装好,这样就等于调用的时候不需要在重复指定参数。可以将一些不希望别人修改的参数封装成闭包函数
在这里插入图片描述

装饰器(很重要)

装饰器就是一个特殊的闭包函数
1、什么是装饰器(就是一个函数,只不过这个函数不是给自己使用的,是给其他函数添加功能的)
器指的是工具,而程序中的函数就具备某一功能的工具
装饰指的是为被装饰器对象添加额外功能,例如打印日志、校验参数等等
2、为什么要用装饰器
软件的维护应该遵循开放封闭原则
开放封闭原则指的是:
软件一旦上线运行后对修改源代码是封闭的,对扩展功能的是开放的
这就用到了装饰器
装饰器的实现必须遵循两大原则:
1、不修改被装饰对象的源代码(人的原来的性格,生活方式)
2、不修改被装饰对象的调用方式(人的原来的外貌,名字)

基本用法


# def run():
#     print('跑步')
#     print('健身')
# run()

# def fitness():
#     print('健身')
#     run()
# def run():
#     print('跑步')
#
# fitness()

# 装饰器其实就在遵循1和2原则的前提下为被装饰对象添加新功能
# 比如男孩1给女朋友买衣服,项链或化妆品  , 变的更加自信,原来的外貌,原来的性格没有发生改变 # 装饰器

# 比如男孩2带女朋友去整容   , 变的更加自信(不一定), 原来的外貌,原来的性格发生改变 # 不是装饰器
# 装饰器
name = '小王'
def run(name):
    print('=========')
    print('我是%s'%name)
    print('=========')
    return '你好:%s'%(name)
# run(name)
def decorate(func): # func等下我们要传入的run
    def new_func(name): #  run(name) 的name
        print('函数执行前的日志 参数: %s'%(name))
        res = func(name)
        print('函数执行后的日志 返回值: %s'%(res))
        return res
    return new_func
# 一 1.定义了new_func(name)函数 ,2.返回 了new_func内存地址 3.传入了一个run函数名
run=new_func=a=decorate(run)
#print(a)
print(run(name))

在这里插入图片描述

通过注解的方式使用装饰器

简化了 run=new_func=decorate(run) 这一步的连续赋值

name = '小王'
@decorate
def run(name):
    print('=========')
    print('我是%s'%name)
    print('=========')
    return '你好:%s'%(name)
# run(name)
def decorate(func): # func等下我们要传入的run
    def new_func(name): #  run(name) 的name
        print('函数执行前的日志 参数: %s'%(name))
        res = func(name)
        print('函数执行后的日志 返回值: %s'%(res))
        return res
    return new_func
print(run(name))

# 装饰器的要求高于闭包
#         1、不修改被装饰对象的源代码(人的原来的性格,生活方式)
#         2、不修改被装饰对象的调用方式(人的原来的外貌,名字)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

七层汉堡王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值