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 には、次の 2 つの定義方法があります__init__

最初の方法を使用すると、出力は期待どおりになります。
set(['a'])
set(['a'])

2 番目の方法を使用すると、出力が予期しないものになります。
set(['a'])
set(['a', 'b'])

2番目の方法の何が問題になっていますか?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から

関数定義が実行されると、デフォルトのパラメータ値が評価されます。これは、関数が定義されるときに式が一度評価され、同じ「事前に計算された」値が各呼び出しに使用されることを意味します。これは、既定のパラメーターがリストや辞書などの変更可能なオブジェクトである場合に特に重要です。関数がオブジェクトを変更する場合 (たとえば、項目をリストに追加することによって)、既定値は事実上変更されます。

これが、2 番目のメソッドが毎回値を追加する理由です。

さらに、__init__このように2番目を変更します

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

これで、コードを実行すると、常に同じアドレスが得られます ( idCPython の関数は、メモリ内のオブジェクトのアドレスを返します)。したがって、デフォルトの引数は、関数が呼び出されるたびに作成されるのではなく、最初に評価されるときに作成されます。

于 2013-11-06T10:30:58.673 に答える
1

thefourthey は、この動作の原因について完全に正しいです。コンストラクタの 2 番目のバージョンを使用する場合は、次のようにする必要があります。

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 に答える