好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

20201112 函数式编程之参数详解

 总结:
当一个函数/过程没有使用 return 显示的定义返回值时,python 解释器会隐式的返回 None,所以在 python 中即便是过程也可以算作函数。 
 5. 函数返回值:
def test01():
    pass
def test02():
    return 0
def test03():
    return 0,10,'hello',['gabriel','zzz'],{'celestial':'sky'}
t1 = test01()
t2 = test02()
t3 = test03()
print('from test01 return is [%s]:' %type(t1),t1)
print('from test02 return is [%s]:' %type(t2),t2)
print('from test03 return is [%s]:' %type(t3),t3)
--->
from test01 return is [<class 'NoneType'>]: None
from test02 return is [<class 'int'>]: 0
from test03 return is [<class 'tuple'>]: (0, 10, 'hello', ['gabriel', 'zzz'], {'celestial': 'sky'}) 
 001 >>
def test1():
    print('in the test1')
    return 0
    print('test finished')  # 前一步return 0 结束函数,终止运行,所以这一步不会执行了
test1()
# return 命令执行的函数时,结束函数,同时返回 0

# return 0 如何接收到?
# 可以赋给一个变量,x代表接收函数体中的定义的return这个返回值的结果,赋值给x
x = test1()
print(x)
--->
in the test1
in the test1
0 
 002 >>
def test1():
     print('in the test1')
def test2():
     print('in the test2')
     return 0
def test3():
     print('in the test3')
     return 1,'hello',['aether','arthur'],{'name':'aether'}
x=test1()
y=test2()
z=test3()
print(x)
print(y)
print(z)
---> in the test1
---> in the test2
---> in the test3
---> None
---> 0
---> (1, 'hello', ['aether', 'arthur'], {'name': 'aether'})  
# 返回的其实也是一个值,好比超市买东西,装到朔料袋中,装成一个东西
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple

为什么要有返回值?作用是什么?
最重要的作用是想要函数整个执行的结果,程序后面的逻辑需要根据这个返回值进行操作。 
 003 >>
def test1():
     print('in the test1')
def test2():
     print('in the test2')
     return 0
def test3():
     print('in the test3')
     return test2  # 这个叫做高阶函数 
 004 >>
调用方法:
1. test()执行,()表示调用函数test,()内可以有参数也可没有
参数:
1.形参和实参
形参:
  形式参数,不是实际存在,是虚拟变量。
  在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
实参:
  实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参
区别:
  形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元
  实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
2.位置参数和关键字 (标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
3.默认参数
4.参数组 
 004-1 现在变成有参数的函数
def test(x,y):
     print(x)
     print(y)
test(1,2)
# x 和 y 为位置参数,形参和实参位置是一一对应的,个数不能超,少了也不行
# 1传给了x,2传给了y, x y 为形参,1和2是实参,如果不调用这个函数,x和y 永远不会占用空间。
# x=1  1是真实存在于内存中的变量,而 x 只是一个引用的内存地址;1 代表门,x 代表门牌号,只是屋子空间的一个标识而已。 
 004-2 现在换一种方式
def test(x,y):
     print(x)
     print(y)
test(y=1,x=2) 
---> 2
---> 1
# 位置参数调用,与形参一一对应 
 004-3
def test(x,y):
     print(x)
     print(y)
x=1   # 定义一个内存对象,x来引用
y=2
test(y=y,x=x)   # 前面的y是 test中代表的形参,后面的y是实际的值,道理一样的
---> 1
---> 2
# 不管形参的定义顺序,形参叫什么名字,就赋什么值
# 关键字调用,与形参顺序无关
# 以上是关键字调用和位置参数的调用 
 004-4 
如果只有一个是形参调用
def test(x,y):
     print(x)
     print(y)
test(x=2,3)   
---> SyntaxError: positional argument follows keyword argument
# 这样执行是不行的 
 004-5 
如果只有一个是形参调用
def test(x,y):
     print(x)
     print(y)
test(3,y=2)   
---> 3
---> 2
# 3给x y=2给 y 
 004-6
def test(x,y):
     print(x)
     print(y)
test(3,x=2)
---> Exception has occurred: TypeError
---> test() got multiple values for argument 'x'
--->  File "F:\Visual Studio Code\OLDBOTPYFILE_TRIAL\TRIAL.py", line 4, in <module>
--->    test(3,x=2)
# 这种不是位置调用,也不是关键字调用,混一起了,就会报错
# 如果既有关键字调用,又有位置参数调用,按照位置来
# 左边写一个值,是位置调用,右边就一定会传给y,其他的一定是错的,y=2可以,是因为满足了位置关系 
 004-7-1
如果是三个参数呢?
# 关键参数是不能写在位置参数前面的
def test(x,y,z):
     print(x)
     print(y)
     print(z)
test(3,y=2,6)
---> SyntaxError: positional argument follows keyword argument
# 错误,因为关键参数是不能写在位置参数前面的 
 004-7-2
def test(x,y,z):
     print(x)
     print(y)
     print(z)
test(3,z=2,y=6)
---> 3
---> 6
---> 2
# 如果后面是关键参数,这样就是可以的,一定不能放位置参数前面 
 3. 默认参数
3-1-1
def test(x,y=2):
    print(x)
    print(y)
# 在写形参的时候,提前赋值,等于 2 了 
test(1)
---> 
1
2
没有赋值给y,因为 y 是默认等于 2

3-1-2 可以赋值吗?
def test(x,y=2):       
    print(x)
    print(y)
test(1,y=3)          # 关键字调用
---> 
1
3

3-1-3
def test(x,y=2):
    print(x)
    print(y)
test(1,3)           # 位置调用
---> 
1
3
# 默认参数特点:调用函数的时候,默认参数非必须传递
# 用途:
# 1. 默认安装值   比如,安装软件,默认一键安装,和自定义安装的区别
# 2. 比如连接数据库端口号

3-1-4 
1. 默认安装值
def test(x,soft1=True,soft2=True):
    print(x)
2. 比如连接数据库端口号
def conn(host,port=3306):
    pass 
 4. 参数组
def test():
    pass
# 前面提到的,位置参数,关键字参数,默认参数;参数定义好后,都有一个特点,调用个数超过形参,就报错,少了也不行
# 默认参数在参数调用时,可有可无
需求:实参数目不固定,形参应该如何定义?
参数组的定义:*args (变量名随意)
方式1
def test(*args):
    print(args)
test(1,2,3,4,5,5)
# 形参以 *开头,定义一个变量名
方式2
def test(*args):
    print(args)
test(*[1,2,4,5,5])    
# *args = *[1,2,3,4,5] 会变成元组 -→ args = tuple([1,2,3,4,5])
# *代表一个功能,是一个功能代号 
 4-1 将* 和位置参数结合起来
def test1(x,*args):
    print(x)
    print(args)
test1(1,2,3,4,5,6,7)
---> 
1
(2,3,4,5,6,7)
应用:函数在定义时,业务发展一段时间后,参数可能会不够,这样只能改源代码,为了避免不多传一个参数就改源代码就会用到了,以后会经常用到
元组就是 只读列表 
 4-2 可以传字典吗?
def test2(**kwargs):
    print(kwargs)
test2(name='gabriel',age=8,sex = '?')    
# name相当于 key  gabriel 相当于 value;可以无限向下传
# 会将 三个 关键字参数传给 kwargs
---> 
{'name': 'gabriel', 'age': 8, 'sex': '?'}
# 这就是把关键字转换成字典的方式 存放起来
# **kwargs: 把关键字参数,转换成字典的方式 
 4-2-1 可以跟位置参数吗?
def test2(**kwargs):
    print(kwargs)
    print(kwargs['name'])
    print(kwargs['age'])
test2(**{'name':'gabriel','age':8})
---> 
{'name': 'gabriel', 'age': 8}
gabriel
8 
 4-2-2 可以跟位置参数吗?
def test3(name,**kwargs):
    print(name)
    print(kwargs)
test3('gabriel')
---> 
gabriel
{}
# name 必须指定一个值,kwargs 需要指定一个吗? 
 4-2-2-1
def test3(name, **kwargs):
    print(name)
    print(kwargs)
test3('gabriel','xxx')
# 'xxx' 是位置参数,不是关键字参数,所以会报错,相当于给 name 赋值两个
# 所以,应该用 关键字的方式去写

4-2-2-2
def test3(name,**kwargs):
    print(name)
    print(kwargs)
test3('gabriel',age=18000,sex='N')
--->
gabriel
{'age': 18000, 'sex': 'N'}
# 这是和位置参数结合

4-2-3 如果和默认参数加一起
参数组有两种方式
*args 接收多个参数,转成元组的形式
**kwargs 把关键字参数,转换成字典的方式
# 可以把默认参数写在后面吗?不可以!!一定要放前面! 参数组一定要往后放!!
def test4(name,age=10000,**kwargs):
    print(name)
    print(age)
    print(kwargs)
test4('celestial',sex='N',hobby='sleep')
--->
celestial
10000
{'sex': 'N', 'hobby': 'sleep'}

4-2-3-1
def test4(name,age=9999,**kwargs):
    print(name)
    print(age)
    print(kwargs)
test4('gabriel',sex='N',hobby='fly',age=99999999)
--->
gabriel
99999999
{'sex': 'N', 'hobby': 'fly'}
# 结果同样可行,给默认参数赋值时,默认参数可以不赋值,可以以位置参数的方式赋值,也可以关键字赋值对应

4-2-3-2
def test4(name,age=0,**kwargs):
    print(name)
    print(age)
    print(kwargs)
test4('gabriel',99999,sex='N',hobby='sleep',age=10000)
--->
Traceback (most recent call last):
  File "f:/Visual Studio Code/PyFiles/MML/Management_Project_2/blank_module_name/tobp_2.py", line 5, in <module>
    test4('gabriel',99999,sex='N',hobby='sleep',age=10000)
TypeError: test4() got multiple values for argument 'age'
# 多个值给 age了,给默认参数赋值,两种方式,位置参数已经对应了,关键字参数又给对应了一遍,所以报错了 
 4-3 如果全部放在一起弄呢?
def test4(name,age=0,*args,**kwargs):
    print(name)
    print(age)
    print(args)
    print(kwargs)
test4('gabriel',age=10000,sex='N',hobby='sleep')
--->
gabriel
10000
()
{'sex': 'N', 'hobby': 'sleep'}
# *args 接收的是位置参数,不能接收关键字参数
# *args 接收 N 个位置参数,转换成元组的形式
这里的 *args 无法接收位置参数,所以直接变为 空
sex='N',hobby='sleep' 给 kwargs 了,所以是生成字典
位置参数,不能写关键字参数后面 

查看更多关于20201112 函数式编程之参数详解的详细内容...

  阅读:38次