Python进阶-函数默认参数,特别是参数传递为空列表

使用可变类型作为缺省参数,自己练,还有在群里问, 搜索资料等了试了快两个小时, 初学比较慢记录下… 2019-04-15 15.40

代码举例:

第一次

>>> def func(item,item_list=[]):
	     item_list.append(item)
	     print(item_list)

	     
>>> func('iphone')
	     
['iphone']
>>> func('xiaomi',item_list=['oppo','vivo'])
	     
['oppo', 'vivo', 'xiaomi']
>>> func('huawei')
	     
['iphone', 'huawei']
>>> func('huawei',item_list=['oppo1','vivo1'])
	     
['oppo1', 'vivo1', 'huawei']

第二次

>>> def func(item,item_list=[]):
	     item_list.append(item)
	     print(id(item_list))
	     print(item_list)

	     
>>> func('xiaomi',item_list=['oppo','vivo'])
30203656
['oppo', 'vivo', 'xiaomi']
>>> func('huawei')
48941704
['huawei']
>>> func('huawei',item_list=['oppo1','vivo1'])
48891848
['oppo1', 'vivo1', 'huawei']
>>> func('xiaomi',item_list=[])
48941768
['xiaomi']
>>> func('huawei',item_list=[])
48941768
['huawei']
>>> 

第三次

>>> def func(item,item_list=[]):
	print (item_list)
	item_list.append(item)
	print(item_list)

	
>>> func('huawei')
[]
['huawei']
>>> func('huawei',item_list=['oppo1','vivo1'])
['oppo1', 'vivo1']
['oppo1', 'vivo1', 'huawei']
>>> func('iphone')
['huawei']
['huawei', 'iphone']
>>> func('huawei2',item_list=['oppo2','vivo2'])
['oppo2', 'vivo2']
['oppo2', 'vivo2', 'huawei2']
>>> 

第四次 输出不一样的结果

>>> def func(item,item_list=None):    
    if item_list is None:
        item_list = []
        item_list.append(item)        
    else:
        item_list.append(item)
    return item_list

			      
>>> func('phone')
			      
['phone']
>>> func('c', ['a', 'b'])
			      
['a', 'b', 'c']
>>> func('phone')
			      
['phone']
>>> 

第五次 输出不一样的结果 作用同四

>>> def func(item,item_list=[]):
	item_list.append(item)
	print(item_list)
	item_list.clear()

	
>>> func('iphone')
['iphone']
>>> func('huawei')
['huawei']
>>> func('iphone',['A','B'])
['A', 'B', 'iphone']
>>> func('iphone',['A','B'])
['A', 'B', 'iphone']
>>> 

第六次 输出不一样结果,作用同四,五

>>> def  func(item,item_list=None):
	if item_list is None:
		item_list=[]
	item_list.append(item)
	return item_list

>>> func('a')
['a']
>>> func('a',['b','c'])
['b', 'c', 'a']

第六:不可变默认参数 实例

>>> def immutable_test(i = 1):
    print('before operation', id(i))
    i += 1
    print('after operation', id(i))
    return i

	      
>>> print(immutable_test())
	      
before operation 1398500368
after operation 1398500400
2
>>> print(immutable_test())
	      
before operation 1398500368
after operation 1398500400
2
>>> print(immutable_test(i=2))
	      
before operation 1398500400
after operation 1398500432
3
>>> print(immutable_test(2))
	      
before operation 1398500400
after operation 1398500432
3
>>> print(immutable_test(3))
	      
before operation 1398500432
after operation 1398500464
4
>>> id(immutable_test)
	      
49303200
>>> id(immutable_test(2))
	      
before operation 1398500400
after operation 1398500432
1398500432
>>> id(immutable_test(23))
	      
before operation 1398501072
after operation 1398501104
1398501104
>>> 

很明显,第二次调用时默认参数i的值不会受第一次调用的影响。因为i指向的是不可变对象,对i的操作会造成内存重新分配,对象重新创建,那么函数中i += 1之后名字i指向了另外的地址;根据默认参数的规则,下次调用时,i指向的地址还是函数定义时赋予的地址,这个地址的值1并没有被改变。

其实,可变默认参数和不可变默认参数放在这里讨论并没太大的价值,就像其他语言中所谓的值传递还是引用传递一样,不只会对默认参数造成影响。

总结:
最佳实践
不可变的默认参数的多次调用不会造成任何影响,可变默认参数的多次调用的结果不符合预期。那么在使用可变默认参数时,就不能只在函数定义时初始化一次,而应该在每次调用时初始化。

最佳实践是定义函数时指定可变默认参数的值为None,在函数体内部重新绑定默认参数的值。以下是对上面的两个可变默认参数示例最佳实践的应用:

def good_append(new_item, a_list = None):
 
    if a_list is None:
        a_list = []
 
    a_list.append(new_item)
    return a_list
 
print(good_append('1'))
print(good_append('2'))
print(good_append('c', ['a', 'b']))
import datetime as dt
from time import sleep
 
def log_time(msg, time = None):
 
    if time is None:
        time = dt.datetime.now()
 
    sleep(1)
    print("%s: %s" % (time.isoformat(), msg))
 
log_time('msg 1')
log_time('msg 2')
log_time('msg 3')

你可能感兴趣的:(python,人工智能)