标签:not name key str 作用 test 修改 int [1]
定义两个个函数
def foo(xyz=1):
print(xyz)
foo()
foo()
print(xyz)
=====================
def foo(xyz=[]):
xyz.append(1)
print(xyz)
foo()
foo()
print(xyz)
执行结果
In [20]: def foo(xyz=1):
...: print(xyz)
...:
In [21]: foo()
1
In [22]: foo()
1
In [23]: print(xyz)
#----------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-23-b6499aa2e891> in <module>
----> 1 print(xyz)
NameError: name ‘xyz‘ is not defined
In [24]:
================================
In [24]: def foo(xyz=[]):
...: xyz.append(1)
...: print(xyz)
...:
...: foo()
...: foo()
...: print(xyz)
[1]
[1, 1]
#----------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-24-4726e79ae693> in <module>
5 foo()
6 foo()
----> 7 print(xyz)
NameError: name ‘xyz‘ is not defined
def foo(xyz=[], u=‘abc‘, z=123):
xyz.append(1)
return xyz
print(foo(), id(foo))
print(foo.__defaults__)
print(foo(), id(foo))
print(foo.__defaults__)
In [43]: def foo(xyz=[], u=‘abc‘, z=123):
...: xyz.append(1)
...: return xyz
...:
In [44]: print(foo(), id(foo))
...: print(foo.__defaults__)
[1] 2386557664520
([1], ‘abc‘, 123)
In [45]: print(foo(), id(foo))
...: print(foo.__defaults__)
[1, 1] 2386557664520
([1, 1], ‘abc‘, 123) # 引用类型xyz的内容发生了变化,但全局函数foo对象并没有变化,所以其属性__defaults__也不会变化,其中的xyz的地址也没有发生变化,只不过是在列表中追加了一个元素而已,列表对象还是原来的那个列表对象。
结论
- 函数地址并没有变化,就是说函数这个对象并没有变,调用它,它的属性 defaults 中使用元组保存默认值
- xyz的默认值是引用类型,应用类型的元素变动,并不是元组的变化。这和拷贝的原理是类似的。
def foo(w, u=‘abc‘, z=123):
u = ‘xyz‘
z = 789
print(w,u,z)
print(foo.__defaults__)
foo(‘test‘)
print(foo.__defaults__)
In [47]: def foo(w, u=‘abc‘, z=123):
...: u = ‘xyz‘
...: z = 789
...: print(w,u,z)
...:
In [48]: print(foo.__defaults__)
(‘abc‘, 123)
In [49]: foo(‘test‘)
test xyz 789
In [50]: print(foo.__defaults__)
(‘abc‘, 123) # 非引用类型的默认值并没有变化
结论
- 属性 defaults 中使用元组保存所有位置参数默认值,它不会因为在函数体内使用了它而发生改变。
def foo(w, u=‘abc‘, *, z=123, zz=[4,5,6]):
u = ‘xyz‘
z = 789
zz.append(8)
print(w,u,z,zz)
print(foo.__defaults__)
print(foo.__kwdefaults__)
foo(‘test‘)
print(foo.__kwdefaults__)
In [64]: def foo(w, u=‘abc‘, *, z=123, zz=[4,5,6]):
...: u = ‘xyz‘
...: z = 789
...: zz.append(8)
...: print(w,u,z,zz)
...:
In [65]: print(foo.__defaults__)
(‘abc‘,)
In [66]: print(foo.__kwdefaults__)
{‘z‘: 123, ‘zz‘: [4, 5, 6]}
In [67]: foo(‘test‘)
test xyz 789 [4, 5, 6, 8]
In [68]: print(foo.__kwdefaults__)
{‘z‘: 123, ‘zz‘: [4, 5, 6, 8]} # 引类型的关键字的默认值的发生了变化
结论
- 属性 defaults 中使用元组保存所有位置参数默认值,它不会因为在函数提内使用了它而发生改变。
- 属性 kwdefaults 中使用字典保存所有keyword-only参数默认值.(由于是字典,所以是可以修改的)
- * args 和 **kwargs 都是没有缺省值的,因为他们都可以可接收 0 个参数,就没有必要设置缺省值了。
keyword-only 是在 python3.0之后才有的,所以 kwdefaults 也是python3.0之后才有的。
如何做到按需改变呢?看下面的2种方法
xyz都是传入参数或者默认参数的副本,如果就想修改原参数,无能为力
def foo(xyz=[], u=‘abc‘, z=123):
xyz = xyz[:] # 影子拷贝
xyz.append(1)
print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)
--------------------------------------------
In [85]: def foo(xyz=[], u=‘abc‘, z=123):
...: xyz = xyz[:] # 影子拷贝
...: xyz.append(1)
...: print(xyz)
...:
...: foo()
...: print(foo.__defaults__)
...: foo()
...: print(foo.__defaults__)
...: foo([10])
...: print(foo.__defaults__)
...: foo([10,5])
...: print(foo.__defaults__)
[1]
([], ‘abc‘, 123)
[1]
([], ‘abc‘, 123)
[10, 1]
([], ‘abc‘, 123)
[10, 5, 1]
([], ‘abc‘, 123)
--------------------------------------------
In [84]: a = []
...: b =a[:]
...: id(a),id(b)
Out[84]: (1885549915592, 1885549914248) # < -- 切片是浅拷贝的过程,生成了一个新的列表
def foo(xyz=None, u="abc", z=123):
if xyz is None:
xyz = []
xyz.append(1)
print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)
--------------------------------------------
In [86]: def foo(xyz=None, u="abc", z=123):
...: if xyz is None:
...: xyz = []
...: xyz.append(1)
...: print(xyz)
...:
...: foo()
...: print(foo.__defaults__)
...: foo()
...: print(foo.__defaults__)
...: foo([10])
...: print(foo.__defaults__)
...: foo([10,5])
...: print(foo.__defaults__)
[1]
(None, ‘abc‘, 123)
[1]
(None, ‘abc‘, 123)
[10, 1]
(None, ‘abc‘, 123)
[10, 5, 1]
(None, ‘abc‘, 123)
+=
改变了__defaults__属性, +=
是就地修改相当于 extenddef x(a=[]):
a += [5]
print(x.__defaults__)
x()
print(x.__defaults__)
In [78]: def x(a=[]):
...: a += [5]
...: print(x.__defaults__)
...: x()
...: print(x.__defaults__)
([],)
([5],)
+
并没有改变__defaults__ , 是右边通过 +
生成一个新的对象再赋值给左边的变量,并没有堆默认值操作。def y(a=[]):
a = a + [5]
print(y.__defaults__)
y()
print(y.__defaults__)
In [79]: def y(a=[]):
...: a = a + [5]
...: print(y.__defaults__)
...: y()
...: print(y.__defaults__)
([],)
([],)
In [87]: a = ‘abc‘
...: a += "d"
In [88]: a
Out[88]: ‘abcd‘
In [89]: a = "abc"
...: a = a + "d"
In [90]: a
Out[90]: ‘abcd‘
本文链接:https://www.cnblogs.com/shichangming/p/10383563.html
标签:not name key str 作用 test 修改 int [1]
原文地址:https://www.cnblogs.com/shichangming/p/10383563.html