1
#! /usr/bin/python

class my_class:
    # 1. __init__
    def __init__(self):
        self.my_set = set()

    # 2. __init__
    #def __init__(self, arg_set = set()):
    #    self.my_set = arg_set 

c1 = my_class()
c1.my_set.add('a')

print c1.my_set

c2 = my_class()
c2.my_set.add('b')

print c1.my_set

my_class 有两种定义方式__init__

如果我使用第一种方式,输出如预期:
set(['a'])
set(['a'])

如果我使用第二种方式,输出是意外的:
set(['a'])
set(['a', 'b'])

第二种方式有什么问题?修改 C2(一个单独的对象)如何导致修改 c1?

Edit: Updated the question title to reflect specific area of concern

4

2 回答 2

5

来自http://docs.python.org/2/reference/compound_stmts.html#function-definitions

执行函数定义时评估默认参数值。这意味着表达式在定义函数时被计算一次,并且每次调用都使用相同的“预计算”值。当默认参数是可变对象(例如列表或字典)时,这一点尤其重要:如果函数修改了对象(例如,通过将项目附加到列表中),则默认值实际上已被修改。

这就是为什么您的第二种方法每次都附加值的原因。

__init__此外,像这样修改第二个

def __init__(self, arg_set = set()):
   print id(arg_set)
   self.my_set = arg_set 

现在,当您运行代码时,您将始终获得相同的地址(idCPython 中的函数返回内存中对象的地址)。因此,每次调用函数时都不会创建默认参数,而是在第一次评估时创建默认参数。

于 2013-11-06T10:30:58.673 回答
1

thefourtheye 对这种行为的原因是完全正确的。如果你想使用你的构造函数的第二个版本,它应该是这样的:

def __init__(self, arg_set=None):
    if arg_set is None:
        self.my_set = set()
    else:
        self.my_set = arg_set
于 2013-11-06T10:36:35.097 回答