Python 가변 객체 및 불변 객체

3598 단어
Python의 모든 대상은 대상입니다. 대상마다 유일한 id가 있습니다. 대응하는 유형과 값이 있습니다. 그 중에서 id는 대상이 메모리에 있는 위치를 가리킵니다.객체의 값을 수정할 수 있는지 여부에 따라 가변 객체와 불변 객체로 구분됩니다.여기서,
대상 불가: 숫자, 문자열,tuple
가변 객체는 list, dict, set
Python의 변수는 임의의 대상을 가리킬 수 있으며, 변수를 모두 바늘로 보고, 가리키는 대상의 메모리 주소 (대상의 인용) 를 저장할 수 있습니다.

불변 객체


불변 객체의 경우 변수에서 참조하는 불변 객체의 값을 업데이트하려는 경우 새 객체가 작성되고 객체의 참조가 변경됩니다. 예를 들면 다음과 같습니다.
In [41]: x = 1

In [42]: y = x

In [43]: print(id(x))
140719461487648

In [44]: x = 2

In [45]: print(id(y))
140719461487648

In [46]: print(id(x))
140719461487680

In [47]: print(id(2))
140719461487680

위에서 설명한 int 유형의 인스턴스는 다음과 같습니다.
  • 변수를 원하는 값은 메모리에 새로운 대상을 만들고 변수는 새로운 대상을 가리킨다.
  • 값이 1 또는 2인 경우 몇 개의 인용이 가리키는 곳을 막론하고 메모리에 하나의 주소만 차지하고 파이톤 내부에서 인용 계수를 통해 이 주소를 가리키는 인용 개수를 기록하며 인용 개수가 0일 때 쓰레기 수거를 한다.

  • 따라서 불변 대상의 장점은 같은 대상에 대해 몇 개의 인용을 막론하고 메모리에 하나의 주소만 차지하는 것이다. 단점은 업데이트는 새로운 대상을 만들어야 하기 때문에 효율이 높지 않다는 것이다.

    가변 객체


    가변 객체의 경우 예를 들면 다음과 같습니다.
    In [57]: a = [1, 2]
    
    In [58]: b = a
    
    In [59]: print(id(a), id(b))
    1961088949320 1961088949320
    
    In [60]: a.append(3)
    
    In [61]: print(a, b)
    [1, 2, 3] [1, 2, 3]
    
    In [62]: print(id(a), id(b))
    1961088949320 1961088949320
    
    In [63]: a = [1, 2, 3]
    
    In [64]: print(id(a))
    1961088989704
    

    다음을 볼 수 있습니다.
  • 값의 변화는 기존 대상을 바탕으로 업데이트된 것으로 변수 인용의 주소는 변화가 없다.
  • 한 변수에 대한 두 번의 값 부여 작업은 값이 같지만 인용된 주소는 다르다. 즉, 같은 값의 대상이다. 메모리에 여러 부를 저장했고 주소는 다르다.

  • 주의, 우리는 가변 대상의 변화를 연구한다. 연구한 것은 같은 대상이다. 즉, 가변은 append, +=라는 조작을 가리킨다. 새로운 값 부여 조작을 포함하지 않고 값 부여 조작은 새로운 대상을 만들 것이다.예를 들면 다음과 같습니다.
    In [96]: a = [1, 2, 3]
    
    In [97]: b = a
    
    In [98]: a = [1]
    
    In [99]: b
    Out[99]: [1, 2, 3]
    

    매개 변수 전달 문제


    가변 객체와 불변 객체의 특성상 매개변수 전달에 주의가 필요하며, 자세한 내용은 나의 대답을 참고할 수 있다

    깊이 복사와 얕은 복사


    먼저, 예를 들면 다음과 같습니다.
    In [69]: data = [{'name': 'a', 'deleted': True}, {'name' : 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]
    
    In [70]: print(data)
    [{'name': 'a', 'deleted': True}, {'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]
    
    In [71]: def add(data_list):
        ...:     for item in data_list:
        ...:         if item.get('deleted'):
        ...:             data_list.remove(item)
        ...:     return data_list
        ...:
    
    In [72]: add_result = add(data)
    
    In [73]: print(add_result)
    [{'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]
    
    In [74]: print(data)
    [{'name': 'b', 'deleted': False}, {'name': 'c', 'deleted': False}]
    

    dd 방법을 호출한 후에 데이터가 바뀌었음을 발견할 수 있습니다. 다음 코드에서 원래의 데이터를 사용할 수 없습니다. 구체적인 원인은 매개 변수가 그 문제를 전달하는 데 설명되어 있습니다.
    그러나dd 방법에서 데이터의 값을 수정하지 않기를 원한다면 어떻게 해야 합니까?
    이때 깊은 복사와 얕은 복사를 알아야 한다.
    심층 복사와 얕은 복사의 개념:
  • 얕은 복사(shallow copy): 새로운 대상을 구성하여 원래 대상의 인용을 새 대상에 삽입하고 대상의 주소만 복사하며 주소가 가리키는 구체적인 내용을 복사하지 않는다. 즉, 원래 대상의 인용을 여전히 사용한다.실현 방식은 공장 함수(list,set 등), 슬라이드,copy 모듈의copy 방법을 포함한다.
  • 딥 카피(deep copy): 대상과 인용을 복제하고 딥 카피를 받은 대상과 원 대상은 서로 독립적이다.실현 방식:copy 모듈의 deepcopy 방법.

  • 따라서 위 코드는 필요에 따라 다음과 같이 업데이트할 수 있습니다.
    def add(data_list):
        ret_data_list = deepcopy(data_list)
        for item in ret_data_list:
            if item.get('deleted'):
                ret_data_list.remove(item)
        return ret_data_list
    

    이상.

    좋은 웹페이지 즐겨찾기