首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python3.5.2:类意外地更改全局变量

Python3.5.2:类意外地更改全局变量
EN

Stack Overflow用户
提问于 2017-03-27 23:42:25
回答 1查看 141关注 0票数 1

一般来说,我对编程、Python和面向对象的编程都很陌生。对于学校作业,我必须编写一个定义“多项式”类的代码,然后用它找到多项式的根。由于代码的行为不像预期的那样,我开始分析它,并意识到正在修改一个全局变量,即表示多项式的系数列表,即多项式类的“输入”。问题是,我似乎找不出(代码的一部分)是什么导致了这种操作。下面是我使用的代码(相关部分):

代码语言:javascript
复制
#set input list
il=[1,1,-1]

#define B!/(O-1)!, note that O is an "oh":
def pr(O,B):
  p=1
  for i in range(O,B+1):
    p*=i
  return p

#polynomial
class pol:

  #init:
  def __init__(self,L=[0]):
    self.l=L
    self.d=len(L)
    self.n=self.d-1

  #evaluate:
  def ev(self,X=0):
    if X==0:
      return self.l[0]
    else:
      s=self.l[0]
      for i in range(1,self.d):
        s+=self.l[i]*X**i
      return s

  #N-th derivative:
  def der(self,N=1):
    if self.n < N:
      return pol([0])
    else:
      lwork=self.l
      for i in range(N,self.d):
        lwork[i]*=pr(i-N+1,i)
      return pol(lwork[N:])

#define specific polynomial and take derivative:
#---here I have put some extra prints to make clear what the problem is---
f=pol(il)
print(il)
fd=f.der()
print(il)
fd2=f.der(2)
print(il)

现在它应该评估为(至少在我的机器上是这样的)。

代码语言:javascript
复制
[1,1,-1]
[1,1,-2]
[1,1,-4]

虽然我希望它只是第一个列表三次,因为在方法"der“的定义中,我不操作输入列表,或者说,这在我看来是如此。

有人能解释一下发生了什么事吗?我是遗漏了一个(简单的)细节,还是在这里误用了类的某些方面?

为了执行我的代码,我使用了运行在Python3.5.2上的在线编译器(repl.it)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-27 23:52:16

第一:永远不要使用mutable default argument for a function/method of any kind

二:从一个名字分配给另一个名字,如在:

代码语言:javascript
复制
lwork=self.l

只是混叠,lwork就变成了对与self.l相同的list的引用。如果您不想更改self.l,(浅层)复制它,例如:对于像list这样的简单序列

代码语言:javascript
复制
lwork = self.l[:]

这将使新的list具有与self.l相同的值。由于这些值都是不可变的,那么浅层副本就足够了;如果值可能是可变的,则需要使用copy模块的copy.deepcopy来确保副本与原始list没有关联。

类似地,如果您不希望在传递给list初始化器的pol和存储在实例上的list之间保留一个绑定,请复制它,例如:

代码语言:javascript
复制
self.l = list(L)

在本例中,我使用了list(L)而不是L[:],因为它从任何输入可迭代类型获得了一个保证类型(list)。这实际上使可变的默认参数是安全的(因为您总是很浅地复制它,所以从来没有人真正地改变它),但是即使如此,可变的缺省值通常被认为是代码嗅觉,所以最好避免它们。

修复整个__init__方法,您将得到以下结果:

代码语言:javascript
复制
# Mostly to avoid code smell, use immutable default (list constructor converts to list)
def __init__(self, L=(0,)):
    self.l = list(L)      # Create list from arbitrary input iterable
    self.d = len(self.l)  # Get length of now guaranteed list (so iterator inputs work)
    self.n = self.d-1
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43058234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档