programing

파이썬 변수 포인터입니까?

nasanasas 2020. 11. 20. 09:03
반응형

파이썬 변수 포인터입니까? 아니면 그들은 무엇입니까?


파이썬의 변수는 내가 아는 한 포인터 일뿐입니다.

이 규칙에 따라이 코드 조각의 결과를 가정 할 수 있습니다.

i = 5
j = i
j = 3 
print(i)

될 것 3입니다. 하지만 예상치 못한 결과를 얻었습니다 5.

또한 내 Python 책은이 예제를 다루고 있습니다.

i = [1,2,3]
j = i
i[0] = 5
print(j)

결과는입니다 [5,2,3].

내가 무엇을 잘못 이해하고 있습니까?


우리는 그것들을 참조라고 부릅니다. 그들은 이렇게 작동합니다

i = 5     # create int(5) instance, bind it to i
j = i     # bind j to the same int as i
j = 3     # create int(3) instance, bind it to j
print i   # i still bound to the int(5), j bound to the int(3)

작은 정수는 인턴이지만이 설명에서는 중요하지 않습니다.

i = [1,2,3]   # create the list instance, and bind it to i
j = i         # bind j to the same list as i
i[0] = 5      # change the first item of i
print j       # j is still bound to the same list as i

변수는 포인터가 아닙니다. 변수에 할당 하면 이름을 개체에 바인딩 하는 것입니다. 그 이후부터는 이름이 리 바인드 될 때까지 이름을 사용하여 객체를 참조 할 수 있습니다.

첫 번째 예에서 이름 i은 값에 바인딩됩니다 5. 이름에 다른 값을 바인딩 j해도 영향을주지 않으므로 i나중에 인쇄 할 때 값의 i값은 그대로 유지 5됩니다.

두 번째 예에서는 모두 결합 i하고 j받는 동일한 목록 객체입니다. 목록의 내용을 수정하면 목록을 참조하는 데 사용하는 이름에 관계없이 변경 사항을 볼 수 있습니다.

"두 목록이 모두 변경되었습니다"라고 말하면 올바르지 않습니다. 목록은 하나 뿐이지 만이 를 참조하는 두 개의 이름 ( ij)이 있습니다.

관련 문서


파이썬 변수는 객체에 묶인 이름입니다

로부터 문서 :

이름은 개체를 나타냅니다. 이름은 이름 바인딩 작업에 의해 도입됩니다. 프로그램 텍스트 에서 이름 이 나타날 때마다 사용을 포함하는 가장 안쪽의 기능 블록에 설정된 이름의 바인딩을 참조 합니다.

당신이 할 때

i = 5
j = i

다음과 같이하는 것과 같습니다.

i = 5
j = 5

j을 가리 키지 않고 i할당 후에 j그것이 i존재 하는지 모릅니다 . 할당 당시에 가리키고 j있던 모든 i것에 묶여 있습니다.

같은 줄에 할당을 한 경우 다음과 같이 표시됩니다.

i = j = 5

그리고 결과는 똑같을 것입니다.

따라서 나중에

i = 3

j가리키는 내용을 변경하지 않고 바꿀 수 있습니다 . 가리키는 내용을 j = 3변경하지 않습니다 i.

귀하의 예는 목록을 역 참조하지 않습니다.

따라서 이렇게하면 :

i = [1,2,3]
j = i

이 작업을 수행하는 것과 동일합니다.

i = j = [1,2,3]

지금 ij같은 목록을 모두 가리 킵니다. 그런 다음 귀하의 예제는 목록을 변경합니다.

i[0] = 5

파이썬 목록은 변경 가능한 객체이므로 한 참조에서 목록을 변경하고 다른 참조에서 볼 때 동일한 목록이므로 동일한 결과를 볼 수 있습니다.


TLDR : Python 이름 은 자동 역 / 참조가있는 포인터처럼 작동하지만 명시 적 포인터 작업을 허용하지 않습니다. 다른 대상은 포인터와 유사하게 작동하는 간접적을 나타냅니다.


CPython 구현은 내부적 으로 유형의 포인터를PyObject* 사용합니다 . 따라서 이름 의미를 포인터 작업으로 변환 할 수 있습니다. 핵심은 실제 개체이름 을 구분하는 것 입니다.

예제 Python 코드에는 이름 ( i)과 객체 ( 5)가 모두 포함됩니다 .

i = 5  # name `i` refers to object `5`
j = i  # ???
j = 3  # name `j` refers to object `3`

이것은 대략 별도의 이름과 객체를 가진 C 코드로 변환 될 수 있습니다 .

int three=3, five=5;  // objects
int *i, *j;           // names
i = &five;   // name `i` refers to position of object `5`
j = i;       // name `j` refers to referent of `i`
j = &three;  // name `j` refers to position of object `3`

중요한 부분은 "포인터로서의 이름"은 객체를 저장하지 않는다는 것입니다! 우리는 정의하지 *i = five않았지만 i = &five. 이름과 개체는 서로 독립적으로 존재합니다.

이름 은 메모리의 기존 개체 가리 킵니다 .

이름에서 이름으로 할당 할 때 개체가 교환되지 않습니다! 우리가 정의 할 때 j = i이것은 j = &five. 둘 다 다른 것과 연결되어 있지 i않습니다 j.

+- name i -+ -\
               \
                --> + <five> -+
               /    |        5 |
+- name j -+ -/     +----------+

따라서 한 이름의 대상을 변경해도 다른 이름에는 영향을주지 않습니다 . 특정 이름이 가리키는 것만 업데이트합니다.


파이썬에는 또한 속성 참조 ( ), 구독 ( ) 및 슬라이싱 ( ) 같은 다른 종류의 이름과 유사한 요소가 있습니다. 개체를 직접 참조하는 이름과 달리 세 가지 모두 개체의 요소를 간접적으로 참조 합니다.i.ji[j]i[:j]

예제 코드에는 이름 ( i)과 구독 ( i[0])이 모두 포함됩니다 .

i = [1,2,3]  # name `i` refers to object `[1, 2, 3]`
j = i        # name `j` refers to referent of `i`
i[0] = 5     # ???

CPython listPyObject*내부적 으로 포인터 의 C 배열을 사용합니다 . 이것은 다시 대략적인 이름과 객체를 가진 C 코드로 번역 될 수 있습니다.

typedef struct{
    int *elements[3];
} list;  // length 3 `list` type

int one = 1, two = 2, three = 3, five = 5;
list values = {&one, &two, &three};  // objects
list *i, *j;                         // names
i = &values;             // name `i` refers to object `[1, 2, 3]`
j = i;                   // name `j` refers to referent of `i`
i->elements[0] = &five;  // leading element of `i` refers to object `5`

중요한 부분은 우리가 이름을 변경하지 않았다는 것입니다! 우리는 i->elements[0]이름이 가리키는 객체의 요소를 변경 했습니다.

기존 복합 객체의 값이 변경 될 수 있습니다.

When changing the value of an object through a name, names are not changed. Both i and j still refer to the same object, whose value we can change.

+- name i -+ -\
               \
                --> + <values> -+
               /    |  elements | --> [1, 2, 3]
+- name j -+ -/     +-----------+

The intermediate object behaves similar to a pointer in that we can directly change what it points to and reference it from multiple names.


They are not quite pointers, they are references to objects. Objects can be either mutable, or immutable. An immutable object is copied when it is modified. A mutable object is altered in-place. An integer is an immutable object, that you reference by your i and j variables. A list is a mutable object.

In your first example

i=5
# The label i now references 5
j=i
# The label j now references what i references
j=3
# The label j now references 3
print i
# i still references 5

In your second example:

i=[1,2,3]
# i references a list object (a mutable object)
j=i
# j now references the same object as i (they reference the same mutable object)
i[0]=5
# sets first element of references object to 5
print j
# prints the list object that j references. It's the same one as i.

When you set j=3 the label j no longer applies (points) to i, it starts to point to the integer 3. The name i is still referring to the value you set originally, 5.


what ever variable is on the left side of '=' sign is assigned with the value on the right side of '='

i = 5

j = i --- j has 5

j = 3 --- j has 3 (overwrites the value of 5) but nothing has been changed regarding i

print(i)-- so this prints 5


Assignment doesn't modify objects; all it does is change where the variable points. Changing where one variable points won't change where another one points.

You are probably thinking of the fact that lists and dictionaries are mutable types. There are operators to modify the actual objects in-place, and if you use one of those, you will see the change in all variables pointing to the same object:

x = []
y = x
x.append(1)
# x and y both are now [1]

But assignment still just moves the pointer around:

x = [2]
# x now points to new list [2]; y still points to old list [1]

Numbers, unlike dictionaries and lists, are immutable. If you do x = 3; x += 2, you aren't transforming the number 3 into the number 5; you're just making the variable x point to 5 instead. The 3 is still out there unchanged, and any variables pointing to it will still see 3 as their value.

(In the actual implementation, numbers are probably not reference types at all; it's more likely that the variables actually contain a representation of the value directly rather than pointing to it. But that implementation detail doesn't change the semantics where immutable types are concerned.)


In Python, everything is object including the memory pieces themselves that you are returned. That means, when new memory chunk is created (irrespective of what've you created: int, str, custom object etc.), you have a new memory object. In your case this is the assignment to 3 which creates a new (memory) object and thus has a new address.

If you run the following, you see what I mean easily.

i = 5
j = i
print("id of j: {}", id(j))
j = 3
print("id of j: {}", id(j))

IMO, memory wise, this is the key understanding/difference between C and Python. In C/C++, you're returned a memory pointer (if you use pointer syntax of course) instead of a memory object which gives you more flexibility in terms of changing the referred address.

참고URL : https://stackoverflow.com/questions/13530998/are-python-variables-pointers-or-else-what-are-they

반응형