짧은 대답은 Python은 항상 값으로 전달하지만 모든 Python 변수는 실제로 일부 객체에 대한 포인터이므로 때때로 참조에 의한 전달처럼 보입니다.
파이썬에서 모든 객체는 변경 가능하거나 변경 불가능합니다. 예를 들어 목록, 딕셔너리, 모듈 및 Pandas 데이터 프레임은 변경 가능하며 정수, 문자열 및 튜플은 변경 불가능합니다. 변경 가능한 객체는 내부적으로 변경 될 수 있지만 (예 : 목록에 요소 추가) 변경 불가능한 객체는 변경할 수 없습니다.
처음에 말했듯이 모든 Python 변수를 객체에 대한 포인터로 생각할 수 있습니다. 함수에 변수를 전달할 때 함수 내의 변수 (포인터)는 항상 전달 된 변수 (포인터)의 복사본입니다. 따라서 내부 변수에 새로운 것을 할당하면 다른 개체를 가리키는 지역 변수. 이것은 변수가 가리키는 원래 객체를 변경 (변형)하지 않으며 외부 변수가 새 객체를 가리 키도록 만들지 않습니다. 이 시점에서 외부 변수는 여전히 원래 개체를 가리 키지 만 내부 변수는 새 개체를 가리 킵니다.
원래 객체를 변경하려면 (변경 가능한 데이터 유형에서만 가능) 로컬 변수에 완전히 새로운 값을 할당 하지 않고 객체를 변경하는 작업을 수행해야 합니다. 이 이유 letgo()
및 letgo3()
변경되지 않은 외부 항목을두고 있지만 letgo2()
변경합니다 그것.
@ursan이 지적했듯이 letgo()
대신 이와 같은 것을 사용 하면 가리키는 원래 객체를 변경 (변형) df
하여 전역 a
변수 를 통해 표시되는 값을 변경합니다 .
def letgo(df):
df.drop('b', axis=1, inplace=True)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo(a)
어떤 경우에는 실제로 직접 할당하지 않고 원래 변수를 완전히 비우고 새 데이터로 다시 채울 수 있습니다. 예를 들어 v
, 가리키는 원래 객체 가 변경되어 v
나중에 사용할 때 표시되는 데이터가 변경 됩니다.
def letgo3(x):
x[:] = np.array([[3,3],[3,3]])
v = np.empty((2, 2))
letgo3(v)
내가 직접 할당하는 것이 아니라는 점에 유의하십시오 x
. 의 전체 내부 범위에 무언가를 할당하고 x
있습니다.
완전히 새로운 개체를 만들고 외부에 표시해야하는 경우 (때로는 pandas의 경우) 두 가지 옵션이 있습니다. 'clean'옵션은 새 객체를 반환하는 것입니다. 예 :
def letgo(df):
df = df.drop('b',axis=1)
return df
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
a = letgo(a)
또 다른 옵션은 함수 외부에 도달하여 전역 변수를 직접 변경하는 것입니다. 이것은 a
새로운 객체를 가리 키도록 변경 되고 a
나중에 참조하는 모든 함수 는 새로운 객체를 보게됩니다.
def letgo():
global a
a = a.drop('b',axis=1)
a = pd.DataFrame({'a':[1,2], 'b':[3,4]})
letgo()
전역 변수를 직접 변경하는 것은 일반적으로 나쁜 생각입니다. 코드를 읽는 사람은 누구나 어떻게 a
변경 되었는지 파악하기가 어렵 기 때문 입니다. (저는 일반적으로 스크립트의 많은 함수에서 사용하는 공유 매개 변수에 전역 변수를 사용하지만 이러한 전역 변수를 변경하도록 허용하지 않습니다.)