2013-05-27 4 views
1

필자는 목록의 사본을 함수에 전달했는데 어떤 이유로 원래 목록이 변경되었습니다. 나는 할 수있는 모든 노력을 기울였습니다. 이것은 완전히 비논리적 인 것이거나 잘못된 것을 저질렀습니다.목록이 이유없이 변경되는 이유는 무엇입니까?

maze="""XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXX   XXXXXXXXXXXXXXXXXXXXX EXX 
XXXXXXXXXXXXXX XXX   XXXX  XXX 
XX XX   XXX XXXXXXX XXXX XXXXXXX 
XX XX XXXXXXXXX XX XXXXXXX XXXX XXXXXXX 
XX XX XXXXXXX XXXXX XXXXXXX XXXX XXXXXXX 
XX XX XXXX XXXXX XXXXX    XX 
XX XX XXXX XX XXXXX XXX XXXXXXXXXXXXXX 
XX XX XXXX XX XXXXXXX XXX  XXXX XX 
XX XX  XX  XXX XXXXXXX XXXX XX XX 
XX XXXXXXXXXX XXX XXX XXXXXXX  XXXXX 
XX  XXXXX XXX XXXXXX  XXXX XXXXX 
XXXX XX XXXXX XXX XX  XXXX XXXX XXX 
XXXX XX XXXXX XXX XX XXXXXXXX XXXXXX XXX 
XX XX XXX XXX XX XXXXX  XXXX XXX 
XXXX XX  XXXXX XXXXX XXXXXXX XXXXX 
XXXX XXXXXXXXXXXXXXXXXXXXX XXXXXXX XXX 
XXXX    XXX  XXXXX XXX 
XXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXXX XXX 
XXX    XXXXXX XXXXXX XXXXX XXX 
XXX XXXXXXXXXXXXXXXXX XX  XXXXX XX 
XXX    XX XX XXXX XXXXXXXXXX XX 
XS XXXXXXXX XXXXX XXXX   XX 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX""" 
grid=maze.split("\n") 
for x in xrange(len(grid)): 
    grid[x]=list(grid[x]) 
row=len(grid) 
col=len(grid[0]) 
def check(maze,x,z,row,col): 
    lim=0 
    if z+1<col and maze[x][z+1]=="X": 
     lim+=1 
    if x+1<row and maze[x+1][z]=="X": 
     lim+=1 
    if z-1>=0 and maze[x][z-1]=="X": 
     lim+=1 
    if x-1>=0 and maze[x-1][z]=="X": 
     lim+=1 
    return lim 
def get_pos(grida,row,col): 
    for l in xrange(100): 
     for x in xrange(len(grida)): 
      for z in xrange(len(grida[x])): 
       if check(grida,x,z,row,col)>=3 and grida[x][z]!="E" and grida[x][z]!="S": 
        grida[x][z]="X" 
       else: 
        continue 
    return grida 
grid_temp=grid[:] 
print grid 
grid_2=get_pos(grid_temp,row,col) 
print grid 

그리드가 실제로 변경되는 이유를 알고 싶습니다.

+0

"왜"로 시작하는 질문은 좋은 생각이 아닙니다. 먼저 목록이 사실 * * * 이유없이 변경되는지 확인하십시오. –

+0

@LutzHorn 당신은 내가 그 이유를 알기를 원한다는 것을 알 수 있습니다. 나는 그것을 찾을 수없는 것 같습니다. grid_temp = 그리드 [:] 인쇄 그리드 grid_2 = get_pos (grid_temp, 행 안부) 인쇄 그리드 그냥 어, 쓰기 속도하는 –

답변

10

그리드 변수는 목록의 목록 인 2D 배열입니다. grid[:]을 수행하면 목록의 새 목록을 만들고 있지만 요소 자체는 여전히 동일한 미로 행에 대한 참조입니다. deepcopy를 원합니다. copy 모듈의 deepcopy 기능

grida[x][y] = ... 

동안 :

+0

짧은 답변 대만족 그것과는 상관이 없다 그 함수 후 변경? : P –

+0

많은 친구들에게 고마움. 이것은 완벽하게 작동합니다. 나는 아직도 배워야 할 것이 많다고 생각하지만, 그렇게 감사하다는 것을 결코 알지 못했습니다. D –

1

간단한 솔루션, 대신 임시 복사의 copy 모듈을 사용 코드에서 다음과 같은 비트에 내려 오는 이유

import copy 
foo = copy.deepcopy(bar) 

가 귀하의 질문에 대답하기 위해, 나는 생각 귀하의 [:] 복사본은 한 레벨 만 깊게 복사하고, 할당은 두 레벨 깊이입니다.

+0

고마워요.하지만 기억하고있는대로 [:] [:]을 시도했습니다. 이걸 주셔서 감사합니다. p –

+1

[:] [:] 한 레벨을 두 번 깊게 복사 중입니다. –

0

너, 내 친구가 네임 스페이스에 문제가 있습니다. new_array = old_array [:]를 시도하십시오. 이것은 배열에 슬라이스가 생기지 만 콜론 앞뒤에 숫자가 없기 때문에 아무것도 잘라 내지 않고 여전히 배열의 복제본을 강제 실행합니다.

명명하고

이름 바인딩 개체를 참조. 이름은 작업 바인딩 이름으로 소개됩니다. 프로그램 텍스트에서 각 이름의 출현은 바인딩이 가장 안쪽의 기능 블록 에 포함되어 있음을 나타냅니다.

블록은 단위로 실행되는 파이썬 프로그램 텍스트입니다. 다음은 블록입니다 : 모듈, 함수 본문 및 클래스 정의. 대화 형으로 입력 된 각 명령은 블록입니다. 스크립트 파일 (인터프리터에 표준 입력으로 제공되거나 인터프리터에 대한 명령 줄 인수로 을 지정하는 파일)은 코드 블록입니다. A 스크립트 명령 (해석기 명령 줄 에 '-c'옵션이 지정된 명령)은 코드 블록입니다. 문자열 인수는 을 내장 함수 "eval()"및 "exec()"에 코드 블록으로 전달했습니다.

코드 블록은 실행 프레임에서 실행됩니다. 프레임은 (디버깅에 사용되는) 몇 가지 관리 정보를 포함하며 코드 블록이 실행 된 후 실행이 계속되는 방식으로 결정합니다. 이 완료되었습니다.

범위은 블록 내에서 이름의 가시성을 정의합니다. 로컬 변수가 블록에 정의되어 있으면 해당 범위에 해당 블록이 포함됩니다.함수 블록에서 정의가 발생하면 포함 된 블록에 이름에 대해 다른 바인딩이 도입되지 않는 한 범위는 정의 된 블록에 포함 된 모든 블록 으로 확장됩니다. 클래스 블록에 정의 된 이름의 범위는 클래스 블록으로 제한됩니다. 메소드의 코드 블록 까지 확장되지 않습니다. 이것은 기능 범위를 사용하여 구현되므로 이해 및 생성자 표현식을 포함합니다.

클래스 A :이 가 다음 실패한다는 것을 의미 A = 42 B = 목록 (a + I를 I에 대한 범위 (10))

이름이 코드 블록에 사용되는

, 가장 가까운 범위를 사용하여 해결됩니다. 코드 블록 에서 볼 수있는 이러한 모든 범위 세트는 블록 환경이라고합니다.

블록에 이름이 바인딩 된 경우 "nonlocal"로 선언하지 않는 한 해당 블록의 로컬 변수 인 입니다. 이름이 모듈 레벨에서 바인드되면 전역 변수입니다. (모듈 코드 블록의 변수는 로컬 및 전역 변수입니다. 변수가 코드 블록 에 사용되었지만 정의되지 않은 경우 변수 인 입니다.

이름이 전혀 발견되지 않으면 "NameError"예외가 발생합니다. 이름이 바인드되지 않은 로컬 변수를 참조하는 경우 "UnboundLocalError"예외가 발생합니다. "UnboundLocalError"는 "NameError"하위 클래스 입니다.

다음 제물 이름 바인딩 : 함수가 파라미터를 "수입"진술 클래스 및 함수 정의 (이들은 정의 블록의 클래스 또는 기능 명에 결합)하고, 경우에 발생 식별자는 타겟 할당 ","루프 헤더 "또는" "다음에"with ""문 또는 "except"절을 사용합니다. "from ... import *"형식의 "import"문 은 밑줄로 시작하는 모듈을 제외하고 가져온 모듈에 정의 된 모든 이름을 바인딩합니다. 이 양식 은 모듈 수준에서만 사용할 수 있습니다.

"del"문에서 발생하는 대상도 에 대한 경계로 간주됩니다 (실제 의미는 이름의 바인딩을 해제하는 것이지만).

각 할당 또는 가져 오기 문은 클래스 또는 함수 정의로 정의 된 블록 내에서 또는 모듈 수준 (최상위 수준 코드 블록)에서 발생합니다.

코드 블록 내의 임의의 위치에서 이름 바인딩 작업이 발생하면 블록 내의 이름 사용은 모두 현재 블록에 대한 참조로 처리됩니다. 바인드되기 전에 블록이 블록 내에서 사용되면 오류가 발생할 수 있습니다. 이 규칙은 미묘합니다. 파이썬에는 선언이 없으며 코드 블록 내의 어느 곳에서나 이름 바인딩 작업을 수행 할 수 있습니다 ( ). 코드 블록의 로컬 변수는 블록의 텍스트 전체를 스캔하여 결정한 일 수 있습니다.

"global"문이 블록 내에서 발생하는 경우 문에 지정된 이름의 모든 사용은 최상위 네임 스페이스에서 해당 이름의 바인딩을 참조합니다. 이름은 글로벌 네임 스페이스, 즉 코드 블록을 포함하는 모듈 의 네임 스페이스와 builtins 네임 스페이스, 모듈 "builtins"의 네임 스페이스를 검색하여 으로 최상위 네임 스페이스에서 해결됩니다. 전역 네임 스페이스가 먼저 검색됩니다. 거기에 이름이 없으면 builtins 네임 스페이스가 검색됩니다. 글로벌 명령문은 이름의 모든 사용에 선행해야합니다.

코드 블록 의 실행과 관련된 내장 명령 네임 스페이스 실제로 이름 글로벌 네임 스페이스에 "내장 명령」를 검색하여 발견된다; 이것은 사전이나 모듈이어야합니다 (후자의 경우 모듈의 사전이 사용됩니다). 기본적으로 "메인" 모듈에 "builtins"이 내장 모듈 "builtins"입니다. 다른 모듈에서 "builtins"은 "builtins"모듈 자체의 사전 별칭입니다. "builtins"은 사용자가 만든 사전으로 설정하여 약한 형태의 제한된 실행을 설정할 수 있습니다.

세부 CPython의 구현 : 사용자 "내장 명령"을 만지지해야한다 그것은 엄격하게 구현 세부 사항입니다. 사용자 builtins 네임 스페이스의 값을 재정의하려면 "builtins"모듈을 "가져 와서"해당 특성을 적절하게 수정해야합니다.

모듈을 처음 가져올 때 모듈의 네임 스페이스가 자동으로 만들어집니다. 스크립트의 기본 모듈은 항상 "메인"입니다.

"global"문은 같은 블록에있는 이름 바인딩 작업 과 동일한 범위를가집니다. 무료 변수 에 대한 가장 가까운 범위를 포함하는 범위가 전역 명령문을 포함하면 사용 가능한 변수는 전역 변수로 처리됩니다.

클래스 정의는 이름을 사용하고 정의 할 수있는 실행 문입니다. 이러한 참조는 이름 확인을위한 일반적인 규칙을 따릅니다. 클래스 정의의 네임 스페이스가 클래스의 속성 사전 이됩니다. 클래스 범위에 정의 된 이름은 메소드에 표시되지 않습니다. 동적 기능

상호 작용


무료 변수를 포함 중첩 범위와 함께 을 사용할 때 파이썬 문이 불법 몇 가지 경우가 있습니다.

변수를 둘러싼 범위에서 참조하는 경우 이름을 삭제하는 것은 불법입니다. 컴파일시 오류가보고됩니다.

함수에서 가져 오기 --- "가져 오기 *"--- 와일드 카드 형식을 사용하고 함수에 0-개의 변수가 포함 된 중첩 된 블록이 포함되어 있으면 컴파일러에서 "SyntaxError"를 발생시킵니다.

"eval()"및 "exec()"함수는 이름 확인을 위해 전체 환경에 액세스하지 못합니다. 이름은 로컬 과 발신자의 전역 네임 스페이스에서 확인할 수 있습니다. 자유 변수는 가장 가까운 둘러싸는 네임 스페이스에 있지만 글로벌 네임 스페이스에있는 을 해결하지 않습니다. [1] "exec()"및 "eval()"함수에는 글로벌 및 로컬 네임 스페이스를 무시하고 에 대한 선택적 인수가 있습니다. 하나의 네임 스페이스가 인 경우이 둘 모두에 사용됩니다.

관련 항목 : 글로벌, 로컬이 아닌, 할당, 삭제, 동적 기능

관련 문제