Python引用和循环

Python引用和循环,python,loops,object,variables,scope,Python,Loops,Object,Variables,Scope,我习惯于perl,在perl中引用和变量是显式分开的。开始使用python会让生活变得非常混乱。我想在循环中工作,创建对象并将其添加到列表中,但结果令人沮丧。我读过函数定义变量范围的文章,但即使将循环代码封装在函数中,似乎也不能解决这个问题 例如: mylist=[] 课程内容: 定义初始化(self,stuff=[]): self.stuff=stuff 对于范围(10)内的i: obj=事物() obj.stuff.append(1) mylist.append(obj) len(mylis

我习惯于perl,在perl中引用和变量是显式分开的。开始使用python会让生活变得非常混乱。我想在循环中工作,创建对象并将其添加到列表中,但结果令人沮丧。我读过函数定义变量范围的文章,但即使将循环代码封装在函数中,似乎也不能解决这个问题

例如:

mylist=[]
课程内容:
定义初始化(self,stuff=[]):
self.stuff=stuff
对于范围(10)内的i:
obj=事物()
obj.stuff.append(1)
mylist.append(obj)
len(mylist[0]。stuff)

我希望每个对象的“stuff”列表的长度是1,但结果是10。我知道我可以使用deep copy显式地将新创建的对象与以前的对象区分开来,但是有没有更好的方法呢?

这里的问题是,您有相同的
列表
对象被用作使用
thing()创建的所有对象的默认对象

一个可能的解决方案是不使用默认值,如下所示

class thing:
  def __init__(self, stuff):
    self.stuff = stuff

for i in range(10):
  obj = thing(stuff = list())
  print(id(obj.stuff))

这会在for循环的每次迭代中为
stuff
成员分配一个新的
列表。

这里的问题是,您使用相同的
列表
对象作为使用
thing()创建的所有对象的默认对象

一个可能的解决方案是不使用默认值,如下所示

class thing:
  def __init__(self, stuff):
    self.stuff = stuff

for i in range(10):
  obj = thing(stuff = list())
  print(id(obj.stuff))

这会在for循环的每次迭代中为
stuff
成员分配一个新的
列表

当可变列表对象被定义为参数时,它会传递给类


课程内容:
定义初始化(self,stuff=[]):
self.stuff=stuff
对于范围(10)内的i:
obj=事物()
打印(obj)
obj.stuff.append(1)
打印(对象内容)
mylist.append(obj)
打印(mylist)
[1] []

[1, 1] [,]

[1, 1, 1] [,]

[1, 1, 1, 1] [,]

[1, 1, 1, 1, 1] [,]

[1, 1, 1, 1, 1, 1] [,,]

[1, 1, 1, 1, 1, 1, 1] [,,]

[1, 1, 1, 1, 1, 1, 1, 1] [,,,]

[1, 1, 1, 1, 1, 1, 1, 1, 1] [,,,]

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [,,,,,]

在功能块内实例化列表时,每次都会创建一个新列表

下面是使用下面的类时的输出

类事物:
__初始化(self,stuff):
如果是:
self.stuff=stuff
其他:
self.stuff=[]
对于范围(10)内的i:
obj=事物()
打印(obj)
obj.stuff.append(1)
打印(对象内容)
mylist.append(obj)
打印(mylist)
输出

[1] []

[1] [,]

[1] [,]

[1] [,]

[1] [,]

[1] [,,]

[1] [,,]

[1] [,,,]

[1] [,,,]

[1]
[,,,,,]

尝试一下,当可变列表对象被定义为参数时,它会传递给类


课程内容:
定义初始化(self,stuff=[]):
self.stuff=stuff
对于范围(10)内的i:
obj=事物()
打印(obj)
obj.stuff.append(1)
打印(对象内容)
mylist.append(obj)
打印(mylist)
[1] []

[1, 1] [,]

[1, 1, 1] [,]

[1, 1, 1, 1] [,]

[1, 1, 1, 1, 1] [,]

[1, 1, 1, 1, 1, 1] [,,]

[1, 1, 1, 1, 1, 1, 1] [,,]

[1, 1, 1, 1, 1, 1, 1, 1] [,,,]

[1, 1, 1, 1, 1, 1, 1, 1, 1] [,,,]

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] [,,,,,]

在功能块内实例化列表时,每次都会创建一个新列表

下面是使用下面的类时的输出

类事物:
__初始化(self,stuff):
如果是:
self.stuff=stuff
其他:
self.stuff=[]
对于范围(10)内的i:
obj=事物()
打印(obj)
obj.stuff.append(1)
打印(对象内容)
mylist.append(obj)
打印(mylist)
输出

[1] []

[1] [,]

[1] [,]

[1] [,]

[1] [,]

[1] [,,]

[1] [,,]

[1] [,,,]

[1] [,,,]

[1]
这是Python的一个怪癖。在定义函数时,参数的默认值只构造一次。所以,你可以得到这种奇怪的行为:

def f(x=[]):
    x.append('x')
    return x

f()
# ['x']
f()
# ['x', 'x']
f()
# ['x', 'x', 'x']
[]
替换为
list()
,将不会有任何帮助,因为在定义函数时,仍然只对其求值一次。然后,每次调用函数时,同一对象将被重新用作默认对象

为了避免这种情况,您需要使用sentinel,然后显式测试它是否被覆盖。这是一种常见的模式:

def f(x=None):
    if x is None:
        x = []
    x.append('x')
    return x

f()
# ['x']
f()
# ['x']
f(['a', 'b'])
# ['a', 'b', 'x']

这是Python的一个怪癖。在定义函数时,参数的默认值只构造一次。所以,你可以得到这种奇怪的行为:

def f(x=[]):
    x.append('x')
    return x

f()
# ['x']
f()
# ['x', 'x']
f()
# ['x', 'x', 'x']
[]
替换为
list()
,将不会有任何帮助,因为在定义函数时,仍然只对其求值一次。然后,每次调用函数时,同一对象将被重新用作默认对象

为了避免这种情况,您需要使用sentinel,然后显式测试它是否被覆盖。这是一种常见的模式:

def f(x=None):
    if x is None:
        x = []
    x.append('x')
    return x

f()
# ['x']
f()
# ['x']
f(['a', 'b'])
# ['a', 'b', 'x']

这回答了你的问题吗?这回答了你的问题吗?谢谢大家-我正在慢慢习惯这条蛇的运作方式谢谢大家-我正在慢慢习惯这条蛇的运作方式