一、引子

1、函数是什么

用函数与不用函数

#1、代码的组织结构不清晰,可读性差
#2、遇到重复的功能只能重复编写实现代码,代码冗余
#3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大 

函数是带名字的代码块,用于完成具体的工作。

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

现实比拟:

想象生活中的例子,修理工需要实现准备好工具箱里面放好锤子,扳手,钳子等工具,然后遇到锤钉子的场景,拿来锤子用就可以,而无需临时再制造一把锤子。

修理工===>程序员
具备某一功能的工具===>函数 要想使用工具,需要事先准备好,然后拿来就用且可以重复使用
要想用函数,需要先定义,再使用

2、函数分类

#内置函数

对于一些常见,常用的功能,python都给我门内置好了,直接拿起来用就好了。

python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()

#自定义函数

很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。

例如:

def greet_user():
'''显示简单的问候语'''
print('Hello')
greet_user()

3、用函数是为解决以下问题

1、代码的组织结构不清晰,可读性差

2、遇到重复的功能只能重复编写实现代码,代码冗余

3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大

二、定义函数

1、定义一个函数

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

2、函数语法

  

#语法
def 函数名(参数1,参数2,参数3,...):
'''注释'''
函数体
return 返回的值 #函数名要能反映其意义
def auth(user:str,password:str):
'''
auth function
:参数 user: 用户名
:参数 password: 密码
:return: 认证结果
'''
if user == 'allen' and password == '':
return 666
# print(auth.__annotations__) #{'user': <class 'str'>, 'password': <class 'str'>, 'return': <class 'int'>} user=input('用户名>>: ').strip()
pwd=input('密码>>: ').strip()
res=auth(user,pwd)
print(res)
#结果如下
用户名>>: allen
密码>>: 123
666

实例

3、向函数传递信息

eg:

def greet_user():
'''显示简单的问候语'''
print('Hello')
greet_user()

只需要稍作修改,就可以让函数greet_user()不仅向用户显示Hello!,还将用户的名字用作抬头。为此,可在函数定义def greet_user()的括号内添加username。通过在这里添加username,就可以让函数接受你给username指定的任何值。

eg:

def greet_user(username):
'''显示简单的问候语'''
print('Hello '+username.title()+' !')
name=input('请输入你的用户名 >>> ')
greet_user(name) #结果如下
请输入你的用户名 >>>  allen
Hello Allen

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

便于理解:函数类似“变量”,“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名
#test 1
def greet_user():
'''显示简单的问候语'''
print('Hello ')
password()
greet_user() #报错 因为password()没有定义 却调用了 #test 2
def greet_user():
'''显示简单的问候语'''
print('Hello ')
password()
def password():
'''密码'''
print('password ')
greet_user() # 正常 #结论:函数的使用,必须遵循原则:先定义,后调用
#我们在使用函数时,一定要明确地区分定义阶段和调用阶段
#定义阶段
def greet_user():
'''显示简单的问候语'''
print('Hello ')
password()
def password():
'''密码'''
print('password ')
#调用阶段
greet_user()

 5、函数在定义阶段都干了哪些事?

#只检测语法,不执行代码
也就说,语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道

6、定义函数的三种形式

1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印
2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值
3、空函数:设计代码结构
#定义阶段
def tell_tag(tag,n): #有参数
print(tag*n) def tell_msg(): #无参数
print('hello world') #调用阶段
tell_tag('*',12)
tell_msg()
tell_tag('*',12) '''
************
hello world
************
''' #结论:
#1、定义时无参,意味着调用时也无需传入参数
#2、定义时有参,意味着调用时则必须传入参数

有参 and 无参

def auth(user,password):
'''
auth function
:param user: 用户名
:param password: 密码
:return: 认证结果
'''
pass def get(filename):
'''
:param filename:
:return:
'''
pass def put(filename):
'''
:param filename:
:return:
'''
def ls(dirname):
'''
:param dirname:
:return:
'''
pass #程序的体系结构立见 空函数

空函数

三、调用函数

1、调用函数

定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

如下实例调用了 printme() 函数:

函数的调用:函数名加括号 
1 先找到名字
2 根据名字调用代码 # 定义函数
def printme( str ):
"打印任何传入的字符串"
print (str);
return; # 调用函数
printme("我要调用用户自定义函数!");
printme("再次调用同一函数");

以上实例输出结果:

我要调用用户自定义函数!
再次调用同一函数

2、函数返回值

无return->None
return 1个值->返回1个值
return 逗号分隔多个值->元组
什么时候该有返回值?
    调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
    通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
什么时候不需要有返回值?
    调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值
    通常无参函数不需要有返回值

3、函数调用的三种形式

1 语句形式:foo()
2 表达式形式:3*len('hello')
3 当中另外一个函数的参数:range(len('hello'))

四、函数的参数

1、实参与形参

方便于理解:形参类似于变量名,实参类似于变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定

形参(形式参数):指的是在定义函数时,括号内定义的函数,形参其实就变量名   (位置形参,默认形参)

实参(实际参数):指的是在调用函数时,括号内传入的值,实参其实就变量的值

2、位置参数

位置参数:位置即顺序,位置参参数指的就是按照从左到右的顺序依次定义的参数
位置形参:必选参数
位置实参:按照位置给形参传值

位置参数分两种:

  在定义函数时,按照位置定义的形参,称为位置形参

  在定义函数时,按照位置定义的实参,称为位置实参

#在定义函数时,按照位置定义的形参,称为位置形参
def foo(x,y,z):
print(x,y,z)
#注意:
#位置形参的特性是:在调用函数时必须为其传值,而且多一个不行,少一个不行
foo(1,2) #TypeError: foo() missing 1 required positional argument: 'z'
#TypeError: foo()缺失1个必需的位置参数:“z”
foo(1,2,3,4) #TypeError: foo() takes 3 positional arguments but 4 were given
#foo(1、2、3、4)#TypeError: foo()接受3个位置参数,但4个是给定的。
#在调用函数时,按照位置定义的实参,称为位置实参
#注意:位置实参与形参一一对应
foo(1,3,2) #return:1 3 2

位置参数 示例

3、关键字实参

在调用函数时,按照key=value的形式定义的实参,称为关键字参数

因为关键字实参将key=value(名称-值对)将名称和值关联起来了,因此向函数传递参数时不会混淆。所以关键字实参不需要考虑函数调用中的实参顺序

注意的问题:

      1. 关键字实参必须在位置实参右面

      2. 对同一个形参不能重复传值

  

#1、相当于指名道姓地为形参传值,意味着即便是不按照顺序定义,仍然能为指定的参数传值
def foo(x,y,z):
print(x,y,z)
foo(x=1,y=3,z=6) #return:1 3 6
#2、在调用函数时,位置实参与关键字实参可以混合使用,但必须遵守
#1:必须遵循形参的规则
# foo(1,z=3,y=2) #return: 1 2 3
foo(1,z=3) # TypeError: foo() missing 1 required positional argument: 'y'
#2:不能为同一个形参重复传值
foo(1,x=1,z=2,y=3) # TypeError: foo() got multiple values for argument 'x'
#3:位置实参必须放到关键字实参的前面
foo(z=3,y=2,1) #SyntaxError: positional argument follows keyword argument

关键字 示例

4、默认参数(默认值)

在定义阶段,已经为某个形参赋值,那么该形参就称为默认参数

可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)

注意的问题:

      1. 只在定义时赋值一次

      2. 默认参数的定义应该在位置形参右面

      3. 默认参数通常应该定义成不可变类型

应用:
   对于经常需要变化的值,需要将对应的形参定义成位置形参
   对于大多数情况值都一样的情况,需要将对应的形参定义成默认形参

#在定义阶段已经有值,意味着在调用阶段可以不传值
def register(name,age,sex):
print(name,age,sex) register('egon',18,'mele')
register('dai',36,'female')
register('wxx',16,'male')
register('allen',15,'male') #输出如下
egon 18 mele
dai 36 female
wxx 16 male
allen 15 male #我门可以看出基本都是性别是男人,所以我们可以为性别sex设置默认值
def register(name,age,sex='male'):
print(name,age,sex) register('egon',18,)
register('dai',36,'female')
register('wxx',16,)
register('allen',15,) #输出如下
egon 18 male
dai 36 female
wxx 16 male
allen 15 male #位置形参必须在默认参数前面
def register(name,sex='male',age): #SyntaxError: non-default argument follows default argument
print(name,age,sex) #默认参数的值只在定义阶段赋值一次,也就是说默认参数的值在定义阶段就固定死了
m=10
def foo(x,y=m):
print(x,y)
m='aaaaaa'
foo(1) #return: 1 10 #按照变量的定义应该是1 aaaaa,所以说明了默认参数的值只在定义阶段赋值一次
foo(1,11) #1 11 #记住:默认参数的值应该设置为不可变类型
def register(name,hobby,l=[]): #name='wxx',hobby='play'
l.append(hobby) #l=['play']
print(name,l) # wxx ['play'] register('wxx','play') # wxx ['play']
register('allen','read') # alex ['read']
register('egon','music') # alex ['music'] #输出如下 显然输出的结果是不正确的,所以默认参数的值应该设置为不可变类型
wxx ['play']
allen ['play', 'read']
egon ['play', 'read', 'music'] #解决上述办法如下
def register(name,hobby,l=None): #name='wxx',hobby='play'
if l==None:
l=[]
l.append(hobby) #l=['play']
print(name,l) # wxx ['play'] register('wxx','play') # wxx ['play']
register('allen','read') # alex ['read']
register('egon','music') # alex ['music'] #输出如下
wxx ['play']
allen ['read']
egon ['music']

默认参数 示例

5、可变长参数

可变长指的是实参值的个数不固定
而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs

什么是可变长度参数

  可变长度值的参数的个数可以不固定,实参有按位置定义的实参和按关键字定义的实参

  所以可变长度的实参指的就是按照两种形式定义的实参个数可以不固定,然而实参终究是要给形参传值的

  所以形参必须有两种对应的解决方案来分别处理以上两种形式可变长度的实参

形参里包含*与**:

  *

  **

#==========================形参里包含*与**
# * 会将溢出的 位置实参 全部接受,然后保存成 元组 的形式赋值给args
#args程序员约定俗称的规定
def foo(x,y,z,*args):
print(x,y,z,args)
foo(1,2,3,4,5,6,7,8)
#输出结果
1 2 3 (4, 5, 6, 7, 8) # ** 会将溢出的 关键字实参 全部接受,然后保存成 字典 的形式赋值给kwargs
#kwargs程序员约定俗称的规定,用其他命名不会报错
def foo(x,y,z,**kwargs):
print(x,y,z,kwargs)
foo(x=1,y=2,z=3,a=4,b=5,c=6,d=7,f=8)
#输出结果
1 2 3 {'a': 4, 'b': 5, 'c': 6, 'd': 7, 'f': 8} #==========================实参里包含*与**
#一旦碰到实参加*,就把该实参的值打散
def foo(x,y,z,*args):
print(x,y,z,args) foo(1,2,3,*[4,5,6,7,8]) #列表 1 2 3 (4, 5, 6, 7, 8)
foo(1,2,3,*(4,5,6,7,8)) #元组 1 2 3 (4, 5, 6, 7, 8)
foo('ni','hao','a',*'hello') #字符串 ni hao a ('h', 'e', 'l', 'l', 'o')
foo('ni','hao',*'hello') #参数不够时 自动补位 ni hao h ('e', 'l', 'l', 'o')
#测试的几组数据
def foo(x,y,z,):  #这里没有*args哦!
print(x,y,z) foo(*[1,2,3]) #1 2 3
foo(*[1,2,3,4]) #TypeError: foo() takes 3 positional arguments but 4 were given
foo(*[1,2]) #TypeError: foo() missing 1 required positional argument: 'z'

#一旦碰到实参加*,就把该实参的值打散
def foo(x,y,z,**kwargs):
print(x,y,z,kwargs) foo(1,2,3,**{'a':1,'b':2}) # 1 2 3 {'a': 1, 'b': 2}
def foo(x,y,z,):
print(x,y,z,) foo(1,**{'y':1,'z':2}) # 1 1 2
def foo(x,y,z,):
print(x,y,z,) foo(1,**{'y':1,'z':2,'x':111}) #TypeError: foo() got multiple values for argument 'x'
                   #翻译:TypeError: foo()有多个值用于参数“x”
#组合使用
def index(name,age,gender): #index n. 指标;指数;索引;指针
print('welcome %s %s %s' %(name,age,gender))
def wrapper(*args,**kwargs): #wrapper n. 包装材料;[包装] 包装纸;书皮
# print(args)
# print(kwargs)
index(*args,**kwargs) #三种实参其实都是一个结果
wrapper('allen',age='16',gender='male') #egnder n. 性;性别
wrapper('allen',18,gender='male') #male 男人
wrapper('allen',18,'male') #输出结果 以上三种实参其实都是一个结果
welcome allen 16 male
welcome allen 18 male
welcome allen 18 male
*的应用场景

def sum2(*args): #args=(1,2,3)
    res=0
    for num in args:
        res+=num
    return res print(sum2(1,2,3,4,5,6,7)) ** 的应用场景
def auth(name,pwd,**kwargs):
    print(name)
    print(pwd)
    print(kwargs) # auth('egon','123')
auth(name='egon',pwd='123',group='group1') ############################### def foo(x,y=1,*args,z,**kwargs):
    pass def foo(x,y=1):
    pass def foo(x,*args,**kwargs):
    pass

6、命名关键字参


命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
        可以保证,传入的参数中一定包含某些关键字 def foo(x, y, *args, a=1, b, **kwargs):
print(x, y)
print(args)
print(a)
print(b)
print(kwargs) foo(1, 2, 3, 4, 5, b=3, c=4, d=5)
# 结果:
1 2
(3, 4, 5)
1
3
{'c': 4, 'd': 5} ##################
def auth(*args,**kwargs):
'''
使用方式auth(name='egon',pwd='123')
:param args:
:param kwargs:
:return:
'''
if len(args) != 0:
print(args)
print('必须使用关键字的形式传参')
return
if 'name' not in kwargs:
print(kwargs)
print('必须用指定的key名name')
return
if 'pwd' not in kwargs:
print('必须用指定的key名pwd')
return
name=kwargs['name']
pwd=kwargs['pwd']
print(name,pwd) auth('egon',123)
auth(pwd=123,name='egon')
#结果如下
('egon', 123)
必须使用关键字的形式传参
egon 123

python之旅:函数基础的更多相关文章

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

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

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

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

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

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

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

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

  5. python学习之函数基础

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

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

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

  7. Python之路-函数基础&局部变量与全局变量&匿名函数&递归函数&高阶函数

    一.函数的定义与调用 函数:组织好的.可重复使用的.用户实现单一或者关联功能的代码段.函数能够提高应用的模块性和代码的重复利用率.Python提供了很多内置的函数,比如len等等,另外也可以根据自己的 ...

  8. python中的函数(基础)

    1.什么是函数 函数是指将一组数据的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用函数名即可 (函数就是对功能或者动作的封装) 2.函数的语法和定义 def 函数名() 函数体 调用: ...

  9. python 装饰器函数基础知识

    1.装饰器的本质--一个闭包函数 2.装饰器的功能--在不改变原函数及其调用方式情况下对原函数功能进行拓展 3.带参数和返回值的装饰器 def timer(func): @wraps(func) #使 ...

  10. Python 函数基础、有序集合、文件操作(三)

    一.set 特点: set是一个无序且不重复的元素集合访问速度快:天生解决元素重复问题 方法: 初始化 >>> s1 = set()>>> print(type(s ...

随机推荐

  1. c++ 使用this指针进行串联的函数调用

    如代码所示,在每个成员函数函数体最后返回*this.即可实现串联调用. class Time { public: Time(, , ); Time &setHour(int); Time &a ...

  2. Python更新库

    查看系统里过期的python库,可以用pip命令 [root@vnode33 sim-enb-sgi]# pip list #列出所有安装的库 Package Version ------------ ...

  3. 任务看板-Monday

    工作照

  4. servlet几个常用的方法

    servlet继承了HTTPServlet所以可以重写父类的方法,下面一 一介绍方法Dopost DoGet 比较常用不再介绍. 一.Init(),和Init(ServletConfig config ...

  5. beat冲刺(6/7)

    目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(6/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 ppt制作 视频拍摄 接下来的计划 准备答辩 ...

  6. 关于JoptionPane提示框

    import java.util.*; import javax.swing.JOptionPane; import javax.swing.UIManager; public class Main ...

  7. BNUOJ 52308 We don't wanna work! set模拟

    题目链接: https://acm.bnu.edu.cn/v3/problem_show.php?pid=52308 We don't wanna work! Time Limit: 60000msM ...

  8. hihocoder #1388 : Periodic Signal fft

    题目链接: https://hihocoder.com/problemset/problem/1388 Periodic Signal 时间限制:5000ms内存限制:256MB 问题描述 Profe ...

  9. 【贪心算法】POJ-2376 区间问题

    一.题目 Description Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cle ...

  10. 删除一个数字之后数列gcd最大

    ★实验任务 顾名思义,互质序列是满足序列元素的 gcd 为 1 的序列.比如[1,2,3], [4,7,8],都是互质序列.[3,6,9]不是互质序列.现在并不要求你找出一个互质 序列,那样太简单了! ...