Discuss / Python / 求解释,感激不尽

求解释,感激不尽

Topic source

生健男

#1 Created at ... [Delete] [Delete and Lock User]

在默认参数的那一部分中,使用 def add_end(L=[]): L.append('END') return L 会导致默认参数的改变导致再次计算结果不对 可是 def add_end(L=None): if L is None: L=[] L.append('END') return L 中再次调用时函数内部的L=[]不会变成L=['END']吗?是因为if语句实现了重新判断???不懂啊

Taburiss_713

#2 Created at ... [Delete] [Delete and Lock User]

我个人的理解是第二次调用时仍然没给参数,使得if语句重新赋值覆盖了之前的['END'],不知道这样对不对

函数里面的变量只是个局部变量,当该变量的值作为返回值返回之后,该变量就被“销毁”了。下次再执行该函数时又是另外一个局部变量,不再是同一个了。用C语言来说就是静态变量和自动变量的差别。

生健男

#4 Created at ... [Delete] [Delete and Lock User]

非常感谢,最近又看了看憋得书,确实是这么回事儿,有个局部变量的概念,之前没接触过。

pattision

#5 Created at ... [Delete] [Delete and Lock User]

楼上用局部变量来解释似乎不太对,两个函数中都是局部变量,都不应该出现错误。

感觉应该从“对象”的角度来解释。带有默认参数的函数为每个默认参数构造了一个对象,而且这些对象不会在函数调用后销毁,类似C中的静态变量。

当使用 L.append('END')方法对对象进行操作后,对象就被改变了,下次再载入这个“默认”对象时,其值就不再是 [ ],而是 'END'。

而修改后的函数先进行了判断,如果传入的是默认参数 None,则 L=[ ]——该赋值语句是关键,它重新构造了一个值为 [ ] 的对象并将变量 L 由原来的指向“默认对象”转变为指向这个新构造的对象。此后的 L.append('END') 语句也只会对新构造的对象产生影响,而不会改变“默认对象”。而这个新对象位于函数内部,在函数调用结束后便被销毁,所以下次调用函数不会记住上次的值。

我也是刚开始看教程,看到此处也疑惑了好一阵,以上是我的理解,也许不是很准确,欢迎指正。

我觉得是由于列表可变的缘故. def add_end(L=[]): L.append('END') return L

原先的代码中,定义函数时,变量L默认指向一个内存,内存存储列表[]。引用函数后,变量L指向的内存修改列表[]为['END']。当再次调用函数,变量指向的内存没变,但存储的值变了。 def add_end(L=None): if L is None: L=[] L.append('END') return L

修改后,定义函数时,变量L默认指向一个内存,内存存储None,执行L=[],因为None不可变,会指向另一个内存,内存存储[]。继而修改为['END']。当再次调用函数,变量指向的内存变为存储有None的内存。

如果代码是: def add(x=1): x+=1 return x 每次引用add()值都是2.因为数字不可变,与上同理。 不知道这样解释对不对。

暗恋喂牛

#7 Created at ... [Delete] [Delete and Lock User]

为什么不 加 if L is None 错误了勒,不知道这句的意思,求解

aertawergtxcv

#8 Created at ... [Delete] [Delete and Lock User]

在后来修改的代码中 L=None #设定了如果add_end函数输入为空的时候,L默认为None if L=None, L=[] #如果L是None,则L变为空,所以不会出现两个END

只是用了一个默认的不变的变量而已。 当然如果用其他固定值也可以。 例如

def add_end(L=[999]):
    if 999 in L:
      L=[]
    L.append('END')
    return L

也可以起到相同的作用

欧欧不在

#9 Created at ... [Delete] [Delete and Lock User]

想要在输出移动步骤的同时打印当前ABC上各有几个盘子。 代码如下: def move(n,a,b,c,status): if n==1: print(a,'-->',c) status[a]=status[a]-1 status[c]=status[c]+1 print ('%d %d %d' %(status['A'],status['B'],status['C'])) else: move(n-1,a,c,b,status) move(1,a,b,c,status) move(n-1,b,a,c,status)

status = {'A':2,'B':0,'C':0} move(2,'A','B','C',**status) print (status)

然而结果不如人愿: A --> B 1 1 0 A --> C 1 0 1 B --> C 2 -1 1 {'B': 0, 'A': 2, 'C': 0} 看起来status作为参数传递时,在move函数内无法像C语言一样修改其本来的值。 请教这种情形该如何处理?

兄弟,问题出在def move(n,a,b,c,**status): 你这个变量名和参数名取的一样不好解释

move(n,a,b,c,**status)
**status
表示把status这个dict的所有key-value用关键字参数传入到函数的**status参数,参数status将获得一个dict,注意参数status获得的dict是变量status的一份拷贝,他俩虽然内容是一样,但是指向是不一样。所以你改变参数status不会改变变量statu

解决方法其实很简单,删掉函数定义的星号就行了,代码如下:

def move(n,a,b,c,status):
    if n == 1:
        print(a,'-->',c)
        status[a] = (status[a] - 1)
        status[c] = (status[c] + 1)
        print ('%d %d %d' %(status['A'],status['B'],status['C']))
    else:
        move(n - 1,a,c,b,status)
        move(1,a,b,c,status)
        move( n- 1,b,a,c,status)
Exam = {'A':2,'B':0,'C':0}
move(2,'A','B','C',Exam)
print (Exam)

结果:A --> B 1 1 0 A --> C 0 1 1 B --> C 0 0 2


  • 1

Reply