1

グローバル変数は使用せず、明示的に定義することもありませんが、コードにグローバル変数が含まれているようです。ローカルにするのを手伝ってくれませんか?

def algo(X): # randomized algorithm
    while len(X)>2:
        # do a bunch of things to nested list X
    print(X) 
    # tracing: output is the same every time, where it shouldn't be.
    return len(X[1][1])

def find_min(X): # iterate algo() multiple times to find minimum 
    m = float('inf')
    for i in some_range:
        new = algo(X)
        m = min(m, new)
    return m

X = [[[..], [...]],
     [[..], [...]],
     [[..], [...]]]

print(find_min(X))
print(X) 
# same value as inside the algo() call, even though it shouldn't be affected.

X はグローバル変数のように動作しているようです。ランダム化されたアルゴリズムalgo()は、実際には最初の呼び出しで 1 回だけ実行されます。これは、X が変更された値を保持しているため、whileループ内に収まらないためです。したがって、反復の目的は無効にfind_minなります。

私は python が初めてで、このフォーラムも初めてなので、質問を明確にする必要がある場合はお知らせください。ありがとう。

更新これまでのすべての回答に感謝します。私はそれをほとんど理解していますが、以前にこのようなことをしたことがあり、より幸せな結果が得られました。以下のコードが異なる理由を教えてください。

def qsort(X):
    for ...
        # recursively sort X in place
        count+=1 # count number of operations
    return X, count

X = [ , , , ]
Y, count = qsort(X)
print(Y) # sorted
print(X) # original, unsorted.

ありがとうございました。

更新 II私自身の 2 番目の質問に答えるために、違いは、最初のコード (表示されていません) で list メソッドを使用し、2 番目のコードではそれを使用していないことです。

4

4 に答える 4

4

他の人がすでに指摘しているように、問題はリストが関数への参照として渡されるため、関数本体内のリストは、引数として渡したものとまったく同じオブジェクトです。したがって、関数が実行するすべての変更は、外部から見ることができます。

これを解決するalgoには、渡されたリストのコピーに対して関数を操作する必要があります。

ネストされたリストを操作しているためdeepcopy、モジュールの関数を使用して、関数copyの外部に影響を与えることなく自由に変更できるリストのコピーを作成する必要があります。組み込みlist関数を使用してリストをコピーすることもできますが、浅いコピーしか作成されません。これは、ネストされたリストに必要なものではありません。内部リストは同じオブジェクトへのポインターにすぎないためです。

from copy import deepcopy

def algo (X):
    X = deepcopy(X)
    ...
于 2012-07-08T09:42:17.703 に答える
2

を実行するとfind_min(X)、オブジェクトX(この場合はリスト)が関数に渡されます。その関数がリストを変更する場合(たとえば、リストに追加することによって)、はい、元のオブジェクトに影響します。Pythonは、オブジェクトを関数に渡すという理由だけでオブジェクトをコピーしません。

于 2012-07-08T09:32:38.787 に答える
1

オブジェクトをPython関数に渡すと、オブジェクトはコピーされませんが、オブジェクトへのポインターが渡されます。

これは実行を大幅に高速化するため、理にかなっています。リストが長い場合は、そのすべての要素をコピーする必要はありません。

ただし、これは、渡されたオブジェクト(たとえば、リストX)を変更すると、関数が戻った後でも、変更がそのオブジェクトに適用されることを意味します。

例えば:

def foo(x):
    x.extend('a')
    print x

l = []
foo(l)
foo(l)

印刷します:

['a']

['a'、'a']

于 2012-07-08T09:33:52.343 に答える
0

Pythonリストは変更可能であり(つまり、変更可能です)、関数呼び出しalgo内で使用すると、の値変更されます(つまり、リストの参照渡しです)。たとえば、このSOの質問を参照してください。find_minX

于 2012-07-08T09:34:16.697 に答える