참조로 변수를 어떻게 전달합니까?


질문

 

매개 변수가 참조 또는 값으로 전달됩니까?"원래 '대신'변경 '을 출력하는 코드가'변경 '을 출력 할 수 있도록 참조로 어떻게 통과합니까?

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

답변

 

인수는 과제로 전달됩니다.이후의 이론적 근거는 두 가지입니다.

  1. the parameter passed in is actually a reference to an object (but the reference is passed by value)
  2. some data types are mutable, but others aren't

그래서:

mateable 객체를 메서드로 전달하면 메서드는 동일한 객체에 대한 참조를 가져오고 마음의 기쁨에 돌리게 될 수 있지만 메소드에서 참조를 재발인하면 바깥 쪽 범위가 그것에 대해 알지 못하고끝납니다. 바깥 쪽 참조는 여전히 원래 개체를 가리킬 것입니다. 불변의 객체를 메서드에 전달하면 여전히 바깥 쪽 참조를 다시 인도 할 수 없으며 객체를 돌립니다.

더욱 명확하게하기 위해 몇 가지 예를 살펴 보겠습니다.

list - 변경 가능한 유형

메소드에 전달 된 목록을 수정하려고합니다.

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)

산출:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

전달 된 매개 변수는 OUTER_LIST에 대한 참조이므로 복사본이 아닌 경우, 변형 된 목록 방법을 사용하여 변경 사항이 바깥 쪽 범위에 반영되어 변경됩니다.

이제 매개 변수로 전달 된 참조를 변경하려고 할 때 일어나는 일을 보겠습니다.

def try_to_change_list_reference(the_list):
    print('got', the_list)
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'English']

print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)

산출:

before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']

the_list 매개 변수는 값으로 전달되었으므로 새 목록을 할당하는 것은 메소드 외부의 코드가 볼 수있는 효과가 없었습니다.the_list는 outer_list 참조의 복사본이었고, 우리는 새로운 목록을 가리키고 있지만 outer_list가 가리키는 위치를 변경할 방법이 없었습니다.

문자열 - 불변의 유형

그것은 불변이므로 문자열의 내용을 변경하기 위해 할 수있는 일이 없습니다.

자, 참조를 변경하려고 노력합시다

def try_to_change_string_reference(the_string):
    print('got', the_string)
    the_string = 'In a kingdom by the sea'
    print('set to', the_string)

outer_string = 'It was many and many a year ago'

print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)

산출:

before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago

다시, The_String 매개 변수가 값으로 전달되었으므로 새로운 문자열을 할당하는 것은 방법 외부의 코드가 볼 수있는 효과가 없었습니다.the_string은 Outer_String 참조의 복사본이었고, 우리는 새로운 문자열에 대한 the_string 포인트를 가졌으나 outer_string이 지적한 위치를 변경할 방법이 없었습니다.

나는 이것이 일을 조금 맑게하기를 바랍니다.

편집 : @David가 원래 물었습니다. "실제 참조로 변수를 통과하기 위해 할 수있는 일이 있습니까?"라는 점에 대답하지 않습니다.그걸로 일하자.

우리는 어떻게 이것을 돌아 다니는가?

@ Andrea의 답변이 표시되면 새 값을 반환 할 수 있습니다.이것은 일이 전달되는 방식을 변경하지 않지만, 원하는 정보를 얻을 수 있습니다.

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

반환 값을 사용하지 않으려면 값을 저장하고 함수에 전달하거나 목록과 같은 기존 클래스를 사용하는 클래스를 만들 수 있습니다.

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

이것이 조금 불타는 것 같지만.



답변

문제는 파이썬에있는 변수의 오해에서 비롯됩니다.대부분의 전통적인 언어에 익숙한 경우 다음 순서로 일어나는 일에 대한 정신적 모델이 있습니다.

a = 1
a = 2

A가 값 1을 저장하는 메모리 위치이고 값 2를 저장하기 위해 업데이트 된 메모리 위치이고 Python에서 일이 작동하는 방법은 아니지만 A가 업데이트됩니다.오히려 값 1이있는 객체에 대한 참조로 시작한 다음 값 2가있는 객체에 대한 참조로 재 할당됩니다.이 두 객체는 첫 번째 사람을 참조하지 않더라도 두 개체가 계속 공존 할 수 있습니다.사실 프로그램 내의 다른 수의 다른 참고 문헌에 의해 공유 될 수 있습니다.

매개 변수로 함수를 호출하면 객체가 전달 된 객체를 참조하는 새 참조가 작성됩니다. 이것은 함수 호출에서 사용 된 참조와 별개이므로 해당 참조를 업데이트하고 참조를 참조 할 수있는 방법이 없습니다.새로운 개체.귀하의 예 :

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

def Change(self, var):
    var = 'Changed'

self.Variable은 문자열 객체의 원래 '에 대한 참조입니다.변경을 호출하면 객체에 두 번째 참조 var를 만듭니다.함수 안에서 참조 var var를 다른 문자열 오브젝트의 '변경'으로 재 할당하지만 참조 self.variable은 별도이며 변경되지 않습니다.

이 주위의 유일한 방법은 변경 가능한 객체를 전달하는 것입니다.두 참조 모두 동일한 객체를 참조하기 때문에 객체의 변경 사항은 두 위치 모두에 반영됩니다.

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'


답변

python



답변

그것은 통과 또는 패스로 참조가 아닙니다.Fredrik Lundh에 의해 이것을보십시오 :

http://effbot.org/zone/call-by-Object.htm.

여기에 중요한 견적이 있습니다.

"... 변수 [이름]은 객체가 아닙니다. 다른 변수에 의해 표시되거나 객체가 언급 할 수 없습니다."

예제에서 변경 방법이 호출 될 때 네임 스페이스가 생성됩니다.var는 문자열 객체의 원래 '에 대해 해당 네임 스페이스 내에서 이름이됩니다.그런 다음 두 개의 네임 스페이스에 이름이 있습니다.다음으로 var = '변경'은 새 문자열 객체에 바인드를 바인딩하므로 메소드의 네임 스페이스는 '원본'에 대해 잊어 버리게됩니다.마지막으로, 그 네임 스페이스는 잊어 버렸고 '변경'은 그와 함께 '변경'됩니다.



답변

참조 / 가치 대신 할당으로 전달되는 것들을 생각해보십시오.그렇게하면 정상적인 할당 중에 일어나는 일을 이해하는 한 항상 분명합니다.

따라서 함수 / 메소드에 목록을 전달할 때 목록이 매개 변수 이름에 할당됩니다.목록에 추가하면 목록이 수정됩니다.다음 내부의 목록을 재 할당하면 원래 목록이 변경되지 않습니다.

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print a, b      # prints [1, 2, 3, 4] ['a', 'b']

불변 유형을 수정할 수 없으므로 값으로 전달되는 것처럼 보입니다. int를 함수의 매개 변수에 할당하는 기능을 함수로 할당하는 것 같습니다.당신은 그것을 재 할당 할 수는 있지만 원래 변수 값은 변경되지 않습니다.



답변

파이썬에는 변수가 없습니다

파라미터 전달을 이해하는 열쇠는 "변수"에 대한 생각을 멈추는 것입니다.파이썬에는 이름과 개체가 있습니다. 변수처럼 보이지만 항상 세 가지를 구별하는 것이 유용합니다.

  1. Python has names and objects.
  2. Assignment binds a name to an object.
  3. Passing an argument into a function also binds a name (the parameter name of the function) to an object.

그게 다야.벌칙은이 질문에 부적합합니다.

예시:

a = 1

이것은 A 이름을 값 1을 보유하는 유형 정수의 오브젝트에 바인딩합니다.

b = x

이는 이름 B라는 이름이 현재 x 이름이 바인딩 된 것과 동일한 객체에 바인딩합니다. 그 후, B 이름은 더 이상 x이라는 이름과 아무 관련이 없습니다.

Python 3 언어 참조에서 3.1 절 및 4.2 절을 참조하십시오.

질문의 예제를 읽는 방법

질문에 표시된 코드에서 self.change (self.variable)은 '원래'값을 보유하고 할당 var = 'vanced'를 보유하는 객체로 name var (함수 변경 범위)와 바인딩합니다.함수 변경의 본문)은 동일한 이름을 다시 할당합니다. 일부 다른 객체 (문자열을 유지하지만 완전히 다른 것이 있었을 수있었습니다).

참조로 통과하는 방법

따라서 변경하려는 일이 변경 가능한 객체이면 모든 것이 효과적으로 참조로 전달되므로 문제가 없습니다.

그것이 불변의 물체 (예 : bool, 숫자, 문자열) 인 경우, 이동하는 방법은 변경 가능한 객체로 랩핑하는 것입니다. 이것을위한 Quick-and-Dirty 솔루션은 (self.Variable, [self.variable] 및 함수 수정 var [0]) 대신에 outh.variable 목록입니다. 더 많은 Pythonic 접근 방식은 사소한 하나의 속성 클래스를 도입하는 것입니다.이 기능은 클래스의 인스턴스를 수신하고 속성을 조작합니다.

출처:https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference