在《简书》上看到了一个讨论python函数参数传递的文章,仔细读了几遍,有些不是很明白的地方,于是有了此文,欢迎阅读讨论,如有错误,也欢迎指正:
python中"一切皆对象"的概念想必你一定知道;对于python中函数的参数,虽然在函数定义的时候无法指定对象的类型,但是调用该函数的时候,也并不是什么对象都可以传入的,比如我们查看sum的帮助文档,其描述了可接受的第一个参数是可迭代对象(包括迭代器,list,tuple...),第二个参数start,默认值为0,这个参数需要是一个数字;所以参数的传递一定要类型正确;
Help on built-in function sum in module builtins:
sum(iterable, start=0, /)
Return the sum of a 'start' value (default: 0) plus an iterable of numbers
When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.
那么函数究竟是如何访问参数的呢?
参数和函数都是对象,函数对象内还包含了函数内部变量,我把这些内部变量理解为“函数内部对象”, 相对于“函数内部对象”,我认为 函数参数 属于”函数需要访问的外部对象“, 这里简称为“外部对象”. 这里从两个纬度讨论:
A. 从函数定义时的参数是否有默认值:
如果指定了默认值,这时候,函数定义完成的时候,建立了两个“外部对象”:其中一个外部对象对应参数的默认值, 这个外部对象一直都存在,但是只有通过函数才可以访问到;而建立的另外一个“外部对象”,是和传递过来的参数值相对应,这个外部对象也是一直存在,但是这个对象的值随着每次调用结束而被释放;
如果函数定义的时候没有指定默认值,那么只是建立第二个“外部对象”;
B. 函数调用时候传递的是否为全局变量:
如果函数调用时候,传递的是全局对象,那么这时候,是不会使用 上面描述的第二个”外部对象“,尽管那个对象存在,但是并不会使用;而是直接使用全局对象;
如果函数调用发生的时候,传递的不是全局对象,那么就会使用上面描述的第二个”外部对象“;
而如果函数调用时,根本没有传递任何的参数(只适用于定义时指定了默认值的情形), 那么会使用上面描述的第一个”外部变量“
下面用一个例子来验证上面的看法:
- 无论如何调用,只要没有指定s的值,那么这个对象一直是同一个140276684076680;
- 通过把全局对象c 作为参数进行传递,在函数中l 对象(140276683958752)其实就是c 对象(140276683958752);
- 无论用[1] 还是[2] 作为参数,对象l 都始终不会变化(140276683988360);
- 当没有传递任何参数的时候,l对象始终是:140276684383368
[root@localhost ~]# cat p.py
#!/usr/bin/env python
def myfunc(l=[],s="hello,china!"):
print("ID of object l:%d" % id(l))
print("ID of object s:%d" % id(s))
l+=["abc"]
print(l)
c=["global"] #1
print("ID of object c:%d" % id(c))
print("Using global 'c' as para to call function.")
myfunc(c)
print("Using '[1]' as para call the function.")
myfunc([1])
print("Using '[2]' as para call the function.")
myfunc([2])
print("Call the func directly without pass para.")
myfunc()
myfunc()
myfunc()
[root@localhost ~]#
[root@localhost ~]# ./p.py
ID of object c:140276683958752
Using global 'c' as para to call function.
ID of object l:140276683958752
ID of object s:140276684076680
['global', 'abc']
Using '[1]' as para call the function.
ID of object l:140276683988360
ID of object s:140276684076680
[1, 'abc']
Using '[2]' as para call the function.
ID of object l:140276683988360
ID of object s:140276684076680
[2, 'abc']
Call the func directly without pass para.
ID of object l:140276684383368
ID of object s:140276684076680
['abc']
ID of object l:140276684383368
ID of object s:140276684076680
['abc', 'abc']
ID of object l:140276684383368
ID of object s:140276684076680
['abc', 'abc', 'abc']
本文原创,转载请注明出处