一、 函数定义

1、什么是函数
函数就相当于具备某一功能的工具
函数的使用必须遵循一个原则:
先定义
后调用
2、为何要用函数
代码冗余,程序的组织结构不清晰,可读性差
可维护性、扩展性差
3、如何用函数
# 定义函数
# 定义的语法
def 函数名(参数1,参数2,...):
"""文档描述"""
函数体
return 值 def: 定义函数的关键字;
函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;
括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;
冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;
"""文档描述""": 描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性;
函数体:由语句和表达式组成;
return 值:定义函数的返回值,return是可有可无的。

二、 函数使用的原则:先定义,再调用

1、调用函数
函数的使用分为定义阶段与调用阶段,定义函数时只检测语法,不执行函数体代码,函数名加括号即函数调用,只有调用函数时才会执行函数体代码
定义阶段
函数的使用必须遵循’先定义,后调用’的原则。函数的定义就相当于事先将函数体代码保存起来,然后将内存地址赋值给函数名,
函数名就是对这段代码的引用,这和变量的定义是相似的。没有事先定义函数而直接调用,就相当于在引用一个不存在的’变量名’。
形式一:无参函数
定义函数发生的事情
1)、申请内存空间保存函数体代码
2)、将上述内存地址绑定函数名
3)、定义函数不会执行函数体代码,但是会检测函数体语法
调用函数发生的事情
1)、通过函数名找到函数的内存地址
2)、然后加括号就是触发函数代码的执行
def foo():
print(foo) # foo是函数的内存地址,<function foo at 0x000002B9614C7430>
print('in the foo')
bar() def bar():
print('in the bar') # 调用阶段
foo()

# <function foo at 0x00000191556B9280>
# in the foo
# in the bar

形式二:有参函数
def fun1(x, y):
print(x, y) fun1(1, 2) def fun2(a):
print(a) fun2('hello world') # 1 2
# hello world
形式三:空函数,函数体代码为pass
def fun3(x, y):
pass # pass充当函数体“占位符”
# 三种形式的应用场景
# 函数类似于工厂,参数类似于原料,return产品,场景看你是否需要,pass,主要用于构思框架的时候用

三、 调用函数

1、语句的形式:只加括号调用函数
fun()
2、表达式形式:
def func1(x, y):
res = x + y
return res res1 = func1(1, 2)
print(res1)
# 3、函数调用可以当做参数
res2 = func1(func1(1, 2), 10)
print(res2)

四、 函数返回值

return是函数结束的标志,既函数体代码一旦运行到return会立刻终止函数的运行,并且会将return后的值当作本次运行的结果返回
1、返回None:函数体内没有return
return
return None
2、返回一个值:return 值
3、返回多个值:用逗号分隔开多个值,会被return返回成元组
def func():
return 1, 'an', [1, 23] res = func()
print(func(), type(func())) # (1, 'an', [1, 23]) <class 'tuple'>

五、 函数参数使用

一、形参与实参介绍
形参:在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
def func(x,y):
print(x,y)
实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
func(1,2)
实参和形参之间的关系:
在调用有参函数时,实参(值)会赋值给形参(变量名)。
在Python中,变量名与值只是单纯的绑定关系,而对于函数来说,这种绑定关系只在函数调用时生效,在调用结束后解除。

形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。

实参即在调用函数时,括号内传入的值,值可以是常量、变量、表达式或三者的组合:
#1:实参是常量
res=my_min(1,2)

#2:实参是变量
a=1
b=2
res=my_min(a,b)

#3:实参是表达式
res=my_min(10*2,10*my_min(3,4))

#4:实参可以是常量、变量、表达式的任意组合
a=2
my_min(1,a,10*my_min(3,4))
二、形参与实参的具体使用
2.1 位置参数:在定义函数时,按照从左到右的顺序依次定义形参,称为位置形参,凡是按照这种形式定义的形参都必须被传值
特点:按照顺序与形参一一对应,实参个数比形参个数多一个不行,少一个也不行。
def register(name, age, sex):  # 定义位置形参:name,age,sex,三者都必须被传值
print('Name:{} Age:{} Sex:{}'.format(name, age, sex)) register('lq', 18, 'male') # TypeError:缺少3个位置参数
2.2 关键字参数:在调用函数时,实参可以是key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,
可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值。指名道姓给某个形参传值,可以不参照顺序。
register(sex='male',name='lili',age=18)
需要注意在调用函数时:
实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值
register('lili', sex='male', age=18)  # 正确使用
register(name='lili', 18, sex='male') # SyntaxError:关键字参数name=‘lili’在位置参数18之前
register('lili', sex='male', age=18, name='jack') # TypeError:形参name被重复赋值
2.3 默认参数:在定义函数时,就已经为形参赋值,这类形参称之为默认参数,当函数有多个参数时,
需要将值经常改变的参数定义成位置参数,而将值改变较少的参数定义成默认参数。
特点:在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值
def register(name, age, sex='male'):  # 默认sex的值为male
print('Name:%s Age:%s Sex:%s' % (name, age, sex)) register('tom', 17) # 大多数情况,无需为sex传值,默认为male
register('Lili', 18, 'female') # 少数情况,可以为sex传值female
需要注意:
默认参数必须在位置参数之后
默认参数的值仅在函数定义阶段被赋值一次,准确的说被赋予的是值的内存地址
范例1
m=1
def func(x,y=m):
print(x,y) m=223222
func(2)
范例2
m = ['a', ]
def func(x, y=m): # y--->['a',]的内存地址
print(x, y)
m.append('b')
func(2) # 2 ['a', 'b']
虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型
函数最理想的状态:函数的调用只跟函数本身有关系,不受外界代码的影响

def fun(x, y, z, l=[]):
l.append(x)
l.append(y)
l.append(z)
print(l)
l = ['a', 'b']
fun(1, 2, 3)
print(l) # [1, 2, 3]
# ['a', 'b'] def fund(x,y,z,l=['a','b']):
l.append(x)
l.append(y)
l.append(z)
print(l)
fund(1,2,3)
fund(4,5,6) # ['a', 'b', 1, 2, 3]
# ['a', 'b', 1, 2, 3, 4, 5, 6]

# 推荐使用形式:
def fune(x,y,z,l=None):
if l is None:
l=[]
l.append(x)
l.append(y)
l.append(z)
print(l)
fune(1,2,3)
fune(4,5,6) # [1, 2, 3]
# [4, 5, 6]
2.4 可变长度的位置参数(*与**的用法):参数的长度可变指的是在调用函数时,实参的个数可以不固定,而在调用函数时,
实参的定义无非是按位置或者按关键字两种形式,这就要求形参提供两种解决方案来分别处理两种形式的可变长度的参数
(实参用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接受)
2.4.1 可变长度的位置参数:如果在最后一个形参名前加号,那么在调用函数时,溢出的位置实参,都会被接收,
以元组的形式保存下来赋值给该形参。*后跟的可以实任意的名,但约定俗成应该是args.
(1)
def func(x, y, *args):
print(x)
print(y)
print(args)
func(1, 2, 3, 4, 5, 6)
# 1
# 2
# (3, 4, 5, 6)
# 例:求多个值得和
def func(*args):
res = 0
for item in args:
res += item
return res
res = func(1, 2, 3, 4, 5, )
print(res) # 15

(2)*可以用在实参中,实参中带*,先*后的值打散成位置实参,打散就是一个循环遍历取值。

# 例:
def func(x,y,z):
print(x,y,z)
func(*[1,2,3]) # 1 2 3

(3)形参与实参中都带*

def func(x, y, *args):
print(x)
print(y)
print(args)
func(1, 2, *[3, 4, 5]) # [3,4,5]打散成三个元素,三个元素以元组存
# 1
# 2
# (3, 4, 5)
func(1, 2, [3, 4, 5]) # [3,4,5]一个元素,按元组存
# 1
# 2
# ([3, 4, 5],)
func(*'hello world') # 打散成单个元素,以元组存
# h
# e
# ('l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd')
2.4.2 可变长度的关键字参数
如果在最后一个形参名前加**,那么在调用函数时,溢出的关键字参数,都会被接收,以字典的形式保存下来赋值给该形参
**后跟的可以实任意的名,但约定俗成应该是kargs。
(1)
def func(x, y, **kwargs):
print(x)
print(y)
print(kwargs)
func(1, 2, a=3, c=4, d=5)
# 1
# 2
# {'a': 3, 'c': 4, 'd': 5}

(2)  **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参

def func(x, y, z):
print(x, y, z)
func(**{'x': 3, 'y': 4, 'z': 5})
func(*{'x': 3, 'y': 4, 'z': 5}) # 循环遍历取了key
# 3 4 5
# x y z

(3) 形参与实参中都带*

def func(x, y, **kwargs):
print(x, y, kwargs)
func(1, 2, **{'a': 3, 'b': 4, 'c': 5})
# 1 2 {'a': 3, 'b': 4, 'c': 5}
2.5 命名关键字参数
命名关键字参数:在定义函数时,*后定义的参数,如下所示sex,age,称之为命名关键字参数
想要限定函数的调用者必须以key=value的形式传值,Python3提供了专门的语法:
需要在定义形参时,用作为一个分隔符号,*号之后的形参称为命名关键字参数。
对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值
def register(x, y, *, sex, age):
print(x, y, sex, age)
register(1, 2, sex='male', age=18) # 正确使用
# 1 2 male 18
register(1, 2, 'male', '18') # TypeError:未使用关键字的形式为sex和age传值
2.6 组合使用(*args必须在**kwargs之前)
综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args、命名关键字参数、**kwargs。
可变参数*args与关键字参数**kwargs通常是组合在一起使用的,如果一个函数的形参为*args与**kwargs,
那么代表该函数可以接收任何形式、任意长度的参数。 
def func(*args, **kwargs):
pass
# 例:
def func(x, y, z):
print(x, y, z)
def wrapper(*args, **kwargs):
func(*args, **kwargs)
wrapper(1, z=3, y=2)
# 1 2 3
'''
按照上述写法,在为函数wrapper传参时,其实遵循的是函数func的参数规则,调用函数wrapper的过程分析如下:
位置实参1被接收,以元组的形式保存下来,赋值给args,即args=(1,),关键字实参z=3,y=2被**kwargs接收,
以字典的形式保存下来,赋值给kwargs,即kwargs={'y': 2, 'z': 3}执行func(args,kwargs),即func((1,),**{'y': 2, 'z': 3}),
等同于func(1,z=3,y=2)提示: *args、**kwargs中的args和kwargs被替换成其他名字并无语法错误,但使用args、kwargs是约定俗成的。
'''

六、总结

0、引用传递
python中所有值得传递,传递的都是不是值本身,而是值得引用,既内存地址
1、函数分为两大类,分别是什么?二者在使用时有何区别
内置函数
自定义函数
2、什么是形参、什么是实参?形参与实参之间的关系是什么?
定义阶段和调用阶段
3、简述两只形参的区别:位置形参、默认形参
默认形参就在在定义阶段已给出值
ps:函数最理想的状态是函数的运行不受外界代码的干扰
def func(x,y,z=None):
if z is None:
z=[]
print(z)
4、简述两只实参的区别:位置实参、关键字实参
调用阶段func(1,2,a=3,b=3)
5、简述*和**在形参与实参中的区别(解决调用时,实参的个数与形参的个数不一样的问题)
def func(*args,**kwargs):
pass
func(1,2,3,4,a=5,b=6) 实参带*和**,就是打散,for循环的一个取值;形参中的*和**就汇总成元组和字典。 6、解释下述形式,既函数wrapper的参数特点是什么
def index(x,y,z):
print(x,y,z) def wrapper(*args,**kwargs) #形参汇总,args=(1,2),kwargs={'a':3,'b':4},
index(*args,**kwargs) #调用,实参打散,index(*(1,2),**{'a':3,'b':4})----->index(1,2,a=3,b=4) wrapper(1,2,a=3,b=4)


python基础六(函数基础及参数使用)的更多相关文章

  1. python学习7—函数定义、参数、递归、作用域、匿名函数以及函数式编程

    python学习7—函数定义.参数.递归.作用域.匿名函数以及函数式编程 1. 函数定义 def test(x) # discription y = 2 * x return y 返回一个值,则返回原 ...

  2. Python学习笔记-函数基础

    函数基础 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 为什么使用函数:减少重复代码.使程序变的可扩展使程序变得易维护 1.定义一个函数 #定 ...

  3. python学习总结 --函数基础

    函数基础 ### 函数简介 - 定义:具有特定功能的一段代码 - 优点: - 可以减少代码的重复书写 - 可以将功能的实现着和使用者分开,可以提高开发效率 - 分类: - 库函数:print.inpu ...

  4. Python学习day9 函数Ⅰ(基础)

    函数Ⅰ(基础) 三目运算 基本结构 v =  前面  if 条件 else 后面    #条件为真v=前面,条件为假v=后面.​#等同于if 条件: v = '前面'else:    v = '后面' ...

  5. Day9 Python基础之函数基础(七)

    参考链接:https://www.cnblogs.com/yuanchenqi/articles/5828233.html 1.函数的定义 定义: 函数是指将一组语句的集合通过一个函数名封装起来,要想 ...

  6. python学习日记(函数基础)

    修改文件(原理)--回顾 #修改文件(原理) with open('name','r',encoding='utf-8') as f,\ open('password','w+',encoding=' ...

  7. Python 入门基础12 --函数基础5 匿名函数、内置函数

    今日内容: 1.三元表达式 2.列表.元组生成式 | 字典生成式 3.递归 4.匿名函数 5.内置函数 一.三元表达式 三元运算符:就是 if...else... 语法糖 前提:if 和 else # ...

  8. python学习之函数基础

    第一个python函数: >>> def func_1(): ... print 'hello python' ... >>> func_1() hello pyt ...

  9. python学习之【第八篇】:Python中的函数基础

    1.前言 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 2.函数的定义 定义函数时需要遵守以下规则: 函数代码块以 def 关键词开头 ...

  10. Python 入门基础8 --函数基础1 定义、分类与嵌套使用

    目录 零.了解函数 一.函数的组成 二.函数的定义 三.函数的使用 四.函数的分类 五.函数的嵌套使用 零.了解函数 1.什么是函数 在程序中函数就是具备某一功能的工具 2.为何用函数 为了解决以下问 ...

随机推荐

  1. Delphi2010中TResourceStream流使用

    Resource可以是任意文件(图像.声音.office都可以),直接打包到编译的exe文件中,调用也非常方便 打开一个新的或已有的delphi工程 1.先在 Project->resource ...

  2. [Java]HashMap与ConcurrentHashMap的一些总结

    HashMap与ConcurrentHashMap的一些总结 HashMap底层数据结构 JDK7:数组+链表 JDK8:数组+链表+红黑树 JDK8中的HashMap什么时候将链表转为红黑树? 当发 ...

  3. NC200324 魔改森林

    题目链接 题目 题目描述 曾经有一道叫做迷雾森林的题目,然而牛牛认为地图中的障碍太多,实在是太难了,所以删去了很多点,出了这道题. 牛牛给出了一个n行m列的网格图 初始牛牛处在最左下角的格点上(n+1 ...

  4. CentOS7中搭建GitLab踩坑实录

    今晚闲来无事,尝试了下自己搭建一台git服务器,很多人可能不明白平时自己随手就可以提交代码,为什么还要自己搭建服务器呢?首先你有没有考虑过你是怎么能把代码提交上去的?如果公司突然有一天需要你来负责搭建 ...

  5. Ubuntu20.04/22.04 ESP32 命令行开发环境配置

    ESP32 芯片系列 ESP32分三个系列 ESP32-S ESP32-S3: Xtensa 32位 LX7 双核 240 MHz, 384KB ROM, 512KB SRAM, QFN7x7, 56 ...

  6. mysqlGTID主从同步出现1236错误问题

    从主库xtrabackup备份,配置好gtid复制,从主库的从库复制.一直报错误 Last_IO_Error: Got fatal error 1236 from master when readin ...

  7. Java Base64编码使用介绍

    Base64编码介绍     BASE64 编码是一种常用的字符编码,Base64编码本质上是一种将二进制数据转成文本数据的方案. 但base64不是安全领域下的加密解密算法.能起到安全作用的效果很差 ...

  8. 《深入理解Java虚拟机》(三)类加载机制

    @ 目录 1.什么是类的加载 2.类加载的过程 加载 连接 验证 文件格式验证 元数据验证 字节码验证 符号引用验证 准备 解析: 类或接口的解析 字段解析 类方法解析 接口方法解析 初始化 结束生命 ...

  9. redis7源码分析:redis 多线程模型解析

    多线程模式中,在main函数中会执行InitServerLast void InitServerLast() { bioInit(); // 关键一步, 这里启动了多条线程,用于执行命令,redis起 ...

  10. 红胖子(红模仿)的博文大全:开发技术集合大版本更新v4.0.0

    <红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术.树莓派.三维.OpenCV.OpenGL.ffmpeg.OSG.单片机.软硬结合等等)持续更新中...>大版本更新,更新后版本 ...