函数的参数

# (一)形参与实参介绍
# 形参:在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
# def func(x,y):
# print(x,y)

# 实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
# func(1,2)
# 形参与实参的关系
# 1.在调用阶段,实参(变量值)会绑定给形参(变量名)
# 2.这种绑定关系只能在函数体内使用
# 3.形参和实参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系

# 实参是传入的值,但值可以是以下形式(只要最后是值传入什么形式都可以)
# 形式一:
# func(1,2)

# 形式二
# a=1
# b=2
# func(a,b)


# 形式三
# func('1',2)
#
#
# func(func1(1,2),func2(2,3),333)

# (二)形参与实参的具体使用
# 2.1位置参数:按照从左到右的顺序依次定义的参数称之为位置参数
# 位置形参:在函数定义阶段按照从左到右的顺序直接定义的"变量名"
# 特点是:必须被传值,多一个不行少一个不行
# def func(x,y):
# print(x,y)

# 位置实参:按照从左到右的顺序依次传入的值
# 特点:按照顺序与形参一一对应

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


# 2.2关键字参数
# 关键字实参:在函数调用阶段,按照key=value的形式传入的值
# 特点:指名道姓给某个形参传值,可以完全不参照顺序
# def func(x,y):
# print(x,y)
#
# func(y=2,x=1)

# 混合使用,强调
# 1.位置实参必须放在关键字实参左边
# func(1,y=2)
# func(y=2.1)# 报错

# 2.不能为同一个形参重复传值
# func(1,y=2,3) #报错
# func(1,y=2,3,x=4)#报错

# 2.3默认参数
# 默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数
# 特点:在定义阶段就已经被赋值,意味着在调用阶段可以不用为其赋值
# def func(x,y=3):
# print(x,y)
#
# # func(x=1)
# func(x=1,y=444)

# def register(name,age,gender='男'):
# print(name,age,gender)
#
#
# register('大炮',18)
# register('大炮',18)
# register('大炮',19)
# register('大炮',19,'女')


# 位置形参与默认形参混用,强调:
# 1.位置形参必须在默认形参左边
# def func(x,y=2):
# # def func(y=2,x): #报错
# pass
# 2.默认参数的值是在函数定义阶段被赋值的,准确的说被赋予的是值的内存地址
# 示范1
# m=2
# def func(x,y=m):#y=>2的内存地址
# print(x,y)
#
# m=33333 #后面再将33333赋值给m,此时m已经与函数无关。
# func(1)#1 2
#
# #示范2
# m=[11111,]
# def func(x,y=m):#y=>[11111,]的内存地址
# print(x,y)
#
# m.append(33333)
# func(1)
# 3.虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型
# 函数最理想的状态:函数调用只跟函数本身有关系,不收外界代码影响
# m=[11111,]
# def func(x,y=m):#y=>[11111,]的内存地址
# print(x,y)
#
# m.append(33333)
# func(1)

# 规范
# def func(x,y,z,p=None):
# if p is None:
# p=[]
# p.append(x)
# p.append(y)
# p.append(z)
# print(p)
#
# func(1,2,3)
# func(3,5,6)
#
# new_p=[111,222]
# func(1,2,3,new_p)


# 2.4可变长度参数(*与**的用法) 难点
# 可变长度指的是在调用函数时,传入的值(实参)的个数不固定
# 而实参是用来为形参赋值的,所以对应着,针对溢出的实参必须有对应的形参来接收
# 2.4.1 可变长度的位置参数
# I:*形參名:用來接收溢出的位置实參,溢出的位置实参会被*保存成元组形式,并赋值给*后面的形参名
# *后跟的可以是任意形参名,但是规范要求使用args
# def func(x,y,*args):
# print(x,y,args)
#
# func(1,2,3,4,5,6)#1 2 (3, 4, 5, 6)


# def my_sum(*args):
# res=0
# for item in args:
# res+=item
# return res
# res=my_sum(1,2,3,4)
# print(res)

# II:*可以用在实参中,实参中带*,先将*后的值打散成位置实参
# def func(x,y,z):
# print(x,y,z)

# func(*[11,22,33])#func(11,22,33)

# func(*[11,22])#func(11,22)#报错


# III:形参与实参中都带*
# def func(x,y,*args):
# print(x,y,args)

# func(1,2,[3,4,5,6]) #1 2 ([3, 4, 5, 6],)
# func(1,2,*[3,4,5,6]) #打散成func(1,2,3,4,5,6) 结果为:1 2 (3, 4, 5, 6)


# 2.4.2可变长度的关键字参数
# I:**形參名:用來接收溢出的位置实參,溢出的位置实参会被**保存成字典形式,并赋值给**后面的形参名
# **后跟的可以是任意形参名,但是规范要求使用kwargs
def func(x,y,**kwargs):
print(x,y,kwargs)

# func(1,y=2,a=1,b=2,c=3)#1 2 {'a': 1, 'b': 2, 'c': 3}
# II:**可以用在实参中(**后跟的只能是字典),实参中带**,先将**后的值打散成关键字实参
# def func(x,y,z):
# print(x,y,z)

# func(*{'x':1,'y':2,'z':3}) #x y z
# func(**{'x':1,'y':2,'z':3})# func(x=1,y=2,z=3) 输出结果为1 2 3

# III:形参与实参中都带*
# def func(x,y,**kwargs):
# print(x,y,kwargs)

# func(y=222,x=111,a=333,b=444) #111 222 {'a': 333, 'b': 444}
# func(**{'y':222,'x':111,'a':333,'b':444}) #111 222 {'a': 333, 'b': 444}


# 混用*与**
# *args必须在**kwargs前
# def func(o,*args,**kwargs):
# print(args)
# print(kwargs)
# print(o,args,kwargs)
# func(1,2,3,4,5,6,7,x=1,y=2,z=3) #(2, 3, 4, 5, 6, 7) {'x': 1, 'y': 2, 'z': 3}


# def index(x,y,z,bbb):
# print('index>>',x,y,z,bbb)
#
# def wrapper(a,b,c,d):# a=1 b=2 c=3
# index(a,b,c,d) #index(1,2,3,4)
#
# wrapper(1,2,3,4)#为wrapper传递的参数是给index用的


# 2.5 命名关键字参数(了解)
# 在定义函数时,*后定义的参数如下所示,称之为命名关键字参数
# 特点:
# 1.命名关键字实参必须按照key=value的形式为其传值
# def func(x,y,*,a,b):#其中a和b称之为命名关键字参数
# print(x,y)
# print(a,b)
#
# func(1,2,b=222,a=111)

# 示列
# def func(x,y,*,a,b=222):
# print(x,y)
# print(a,b)
# #
# func(1,2,a=111)

# 2.6组合使用(了解)
# def func(x,y=111,*args,z,**kwargs):
# print()

#
函数的基本使用
"""
1.什么是函数
函数就是相当于具备某一功能的工具
函数的使用必须遵循一个原则
先定义
后调用

2.为何要用函数
1.代码冗余,组织结构不清晰,可读性差
2.可维护性、扩展性差

3.如何使用函数
先定义
三种定义方式

后调用

三种调用方式


返回值
三种返回值形式

"""
# 先定义
#定义的语法

# def 函数名(参数1,参数2,...):
# """文档描述"""
# 函数体
# return 值


#形式一:无参函数
# def fun():
# print('hahahha')
# print('hahahha')
# print('hahahha')
#定义函数发生的事情
#1.申请内存空间保存函数体代码
#2.将上述内存地址绑定函数名
#3.定义函数不会执行函数体代码,但是会检测函数体语法



#调用函数发生的事
#1 通过函数名找到函数的内存地址
#2 然后加括号就是在触发函数代码体的执行
# print(fun)
# fun()


# 示范1
# def bar():
# print('form bar')
#
# def foo():
# bar()
# print('form foo')
#
# foo()

#示范2
# def foo():
# bar()
# print('form foo')
#
#
# def bar():
# print('form bar')
#
# foo()

#示范3
# def foo():
# bar()
# print('form foo')

# foo() #報錯
# def bar():
# print('form bar')
#
# foo()


#形式二:有参函数(参数是原材料,return是产品)
# def func(x,y):
# print(x,y)
#
# func(1,2)


#形式三:空函数
# def func(x,y):
# pass



#三种函数定义方式各用在何处
# 1.无参函数应用场景
# def o ():
# name=input('usename>>:')
# age=input('useage>>:')
# msg='姓名:{},年龄:{}'.format(name,age)
# print(msg)
#
# o()



# 2.有参函数应用场景
# def add(x,y):
# res=x+y
# return res
# add(10,2)
# res=add(10,2)
# print(res)



# 3.空函数应用场景
# def auth_user():
# """user authentication function"""
# pass
#
# def download_file():
# """download file function"""
# pass
#
# def upload_file():
# """upload file function"""
# pass
#
# def ls():
# """list contents function"""
# pass
#
# def cd():
# """change directory"""
# pass
#

# 二.调用函数
#1.语句形式:只加括号调用函数
# o()
# add(1,2)
#2.表达式形式:
# def add(x,y):
# res=x+y
# return res
#賦值表达式
# res=add(10,2)
# print(res)

#数学表达式
# res=add(1,2)*10
# print(res)

#3.函数调用可以当做参数
# res=add(add(1,2),10)
# print(res)


#三、函数返回值
#return是函数结束的标志,即函数体代码一旦运行到return会立刻
#终止函数的运行,并且会将return的值当做本次运行的结果返回:
#1.返回None:函数体内没有return
# return
# return None
#2.返回一個值:return值

# def func():
# return 10
#
#
#
# res=func()
# print(res)
#

#36.返回多個值:用逗號分隔开多个值,会被return返回成元组
# def func():
# return 10,'aa',[1,2]
# res=func()
# print(res,type(res))


函数对象




# 精髓:可以把函数当成变量去用
# func=内存地址
# def func():
# print('from func')


# 1.可以赋值
# f=func()
# print(f,func)
# f()


# 2.可以把函数当做参数传入另外一个函数
# def foo(x):# x=func的内存地址
# # print(x)
# x()

# foo(func) #foo(func的内存地址)

# 3.可以当做函数或另外一个函数的返回值
# def foo(x):#x=func的内存地址
# return x # return func的内存地址
# res=foo(func) #foo(func的内存地址)
# print(res)#res=func的内存地址
# res()#调用内存地址里的数


# 4.可以当做容器类型的一个元素
# p=[func,]
# print(p)
# p[0]()


# dic={'k1':func}
# print(dic)
# dic['k1']()


# def lofin():
# print('登录功能')
#
#
# def transfer():
# print('转账功能')
#
#
# def check_banlance():
# print('查询余额')
#
#
# def withdraw():
# print('提现')
#
#
# dic = {'1': lofin, '2': transfer, '3': check_banlance, '4': withdraw}
#
# while True:
# print("""
# 0 退出
# 1 登录功能
# 2 转账功能
# 3 查询余额
# 4 提现
# """)
# choice = input('请输入命令编号:').strip()
# if not choice.isdigit():
# print('请输入编号,憨批')
# continue
# if choice=='0':
# break
#
# if choice in dic: # 第一次写错了
# dic[choice]()
# else:
# print('您输入的功能不存在')


# 修正
# def lofin():
# print('登录功能')
#
#
# def transfer():
# print('转账功能')
#
#
# def check_banlance():
# print('查询余额')
#
#
# def withdraw():
# print('提现')
#
#
# dic = {'0':['退出',None],
# '1': ['登录功能',lofin],
# '2':['转账功能',transfer] ,
# '3': ['查询余额',check_banlance],
# '4': ['提现',withdraw]}
#
# while True:
# for k in dic:
# print(k,dic[k][0])
# choice = input('请输入命令编号:').strip()
# if not choice.isdigit():
# print('请输入编号,憨批')
# continue
# if choice=='0':
# break
#
# if choice in dic: # 第一次写错了
# dic[choice][1]()
# else:
# print('您输入的功能不存在')




函数嵌套









# 一、储备知识
# *args, **kwargs

# 2.名称空间与作用域:名称空间的“嵌套”关系是在函数定义阶段,即检测语法的时候就已经决定


# 3.函数对象
# 可以把函数(内存地址)当做参数传入
# 可以把函数(内存地址)当做返回值返回


# 4.函数的嵌套定义:


# 5.闭包函数
# def outter(x):
# # x=111
# def wrapper():
# print(x)
#
# return wrapper # outter內的wrapper那個函數的內存地址
#
#
# f = outter(111)

# 二、装饰器
""""
1.什么是装饰器
器指的是工具,可以定义成函数
装饰指的是为其他事物添加额外的东西来点缀

合到一起的解释:
装饰器指的是定义一个函数(工具),该函数是用来为其他函数增加功能的

2.为何要用装饰器
开放封闭原则
开放:指的是拓展功能是开放的
封闭:指的是对修改源代码是封闭的
装饰器解释在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能


3.如何用装饰器





#函数嵌套
#1.函数的嵌套调用:在调用一个函数的过程中又调用其他函数
# def max2(x,y):
# if x>y:
# return x
# else:
# return y
#
# def max4(a,b,c,d):
# #第一步:比较a,b得到res1
# res1=max2(a,b)
# #第二步:比较res1,c得到res2
# res2 = max2(res1, c)
# #第三步:比较res2,d得到res3
# res3 = max2(res2, d)
# return res3
#
# res=max4(1,2,3,4)
# print(res)


#2.函数的嵌套定义:在函数内定义其他函数
# def f1():
# def f2():
# pass

#圆形
# 求圆形的周长:2*pi*radius
# def circle(radius,actiong=0):
# from math import pi
# def perimiter(radius):
# return 2*pi*radius
#
# #求圆形的面积:pi*(radius**2)
# def area(radius):
# return pi*(radius**2)
#
# if actiong==0:
# return 2 * pi * radius
#
# if actiong==1:
# return pi * (radius ** 2)
#
#
# circle(33,actiong=0)
名称空间与作用域










# 名称空间(namespace):存放名字的地方,是对栈区的划分
# 有了名称空间之后,就可以在栈区存放相同的名字,详细的,名称空间 (名称空间只有优先级之分,本身并无嵌套关系,画图只是为了理解)
# 分为三种
# 1.1 内置名称空间
# 存放的名字:存放的是Python解释器内置的名字
# 存活周期:Python解释器启动则产生,Python解释器关闭则销毁。

# 1.2 全局名称空间
# 存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称
# x=10
# if 13>3:
# y=20
# if 3==3:
# z=30
# 以上都是全局名称
# func=函数的内存地址
# def func():
# a=111#不是全局名称
# b=222#不是全局名称

# 存活周期:Python文件执行产生,Python文件运行完成后销毁

# 1.3局部名称空间
# 存放的名字:在调用函数时,运行函数体代码过程产生函数内的名字
# 存活周期:在调用函数时存活,函数调用完毕后则销毁
# def func(a,b):
# a=111#是局部名称
# b=222#是局部名称
#
# func(10.1)
# func(10.2)
# func(10.3)
# func(10.4)
# 调几次产生几次名称空间


# 1.4 名称空间的加载顺序
# 内置名称空间》全局名称空间》局部名称空间 内置与全局空间是一定有的


# 1.5 销毁顺序 :内置名称空间《全局名称空间《局部名称空间


# 1.6 名字的查找优先级:当前所在的位置,向上一层一层查找
# 内置名称空间
# 全局名称空间
# 局部名称空间

# 如果当前在全局名称空间
# 全局名称空间--》内置名称空间 找不到就报错
# input=333
# def fun():
# input=444
# fun()
# print(input)


# 示范1
# def fun():
# print(x)
#
# x=111
# fun() #111
#

# 示范2:名称空间的"嵌套"关系是以函数的定义阶段为准,与调用位置无关。
# x=1
# def fun():
# print(x)
#
#
# def foo():
# x=222
# fun()
#
# foo() #1


# 示范3:函数嵌套定义
# input=111
# def f1():
# def f2():
# # input=333
# print(input)
# input = 222#(还是在f1函数内,在f1内就已经定义,所以还是222)
# f2()
#
# f1()


# 示范4:函数名称的查找顺序以定义阶段为准,即函数的嵌套关系与名字的查找顺序在定义阶段就已经确定好的,与调用位置无关。
# x=111
# def func():
# x = 222
# print(x) #错 变量一定要先定义后引用
#
# func()
#

# 二:作用域-》作用范围
# 全局作用域:内置名称空间 全局名称空间
# 1.全局存活
# 2.全局有效:被所有函数共享


# 局部作用域:局部名称空间的名字
# 1.临时存活
# 2.局部有效:函数内有效


# LEBG #函数嵌套的寻找顺序
#b
#g
# def f1():
# enclosing
# def f2():
#enclosing
# def f3():
#local
# pass



闭包函数








#一、 大前提
# 闭包函数=名称空间与作用域+函数嵌套+函数对象
# 核心点:名字的查找关系是以函数定义阶段为准

# 二、什么是闭包函数
#“闭”:函数指的是该函数是内嵌函数
#“包”:函数指的是该函数包含对外层函数作用域名字的引用(不是对全局作用域)

#闭包函数之名称空间与作用域+函数嵌套
# def f1():
# x=3333333
# def f2():
# print(x)
# f2()
# #
# x=111
# def bar():
# x=44444
# f1()
#
# def foo():
# x=22222
# bar()
#
# foo()


# 闭包函数:函数对象
# def f1():
# x=3333333
# def f2():
# print('函数f2',x)
# return f2()
#
# f=f1()#就是调用f2的内存空间,+()调用f2的值




#四、为何要有闭包函数=》闭包函数的应用
#两种函数传参的方式
#方式一:直接传参
# def f2(x):
# print(x)
#
# f2(1)
# f2(2)
# f2(3)

#方式二:
# def f1(x):
# # x=3
# def f2():
# print(x)
# return f2#調用f2的內存地址
#
# x=f1(1)
# print(x)
#
# x()
#


装饰器




# 总结无参装饰器
# def outter(func):
# def wrapper(*args,**kwargs):
# #1.调用原函数
# #2.为其增加新功能
# res=func(*args,**kwargs)
# return res
# return wrapper
# 有参装饰器模板
# def 有参装饰器(x,y,z):
# def outter(func):
# def wrapper(*args, **kwargs):
# res=func(*args,**kwargs)
# return res
# return wrapper
# return outter














posted on 2020-06-19 00:59  輪滑少年  阅读(157)  评论(0编辑  收藏  举报