슬롯으로 Python 클래스 속도 향상



특수 속성__slots__을 사용하면 예상 결과와 함께 객체 인스턴스가 가질 것으로 예상되는 인스턴스 속성을 명시적으로 지정할 수 있습니다.

  • 빠른 속성 액세스.

  • 메모리 공간 절약.

  • 공간 절약은
  • __dict__ 대신 슬롯에 값 참조를 저장합니다.
  • 부모 클래스가 거부하고 __slots__를 선언하는 경우 거부__dict__ 및 __weakref__ 생성.

  • 클래스에서 객체를 만들 때 객체의 속성은 __dict__라는 사전에 저장됩니다. 이 사전을 사용하여 속성을 가져오고 설정합니다. 객체 생성 후 동적으로 새 속성을 생성할 수 있습니다.

    처음에 first_name과 last_name이라는 2개의 속성이 있는 간단한 클래스 Person을 만들어 봅시다. 객체의 __dict__를 출력하면 각 속성의 키와 값을 얻게 됩니다. 한편, 나중에 필요할 클래스의 __dict__도 인쇄합니다. 그런 다음 새 속성 검토자가 개체에 추가되고 업데이트된 __dict__에서 확인할 수 있습니다.

    class Person:
         def __init__ (self, first_name: str, last_name: str):
             self.first_name = first_name
             self.last_name = last_name
    
    if __name__ == " __main__":
         person = Person("Chidozie", "Okafor")
         print(person. __dict__ )
      {'first_name': 'Chidozie', 'last_name': 'Okafor'}
        print(Person. __dict__ )
    {' __module__': ' __main__', ' __doc__': None, ' __init__': <function __init__ at 0x10e9cd140>}
    


    사전의 문제는 메모리 소비이며 액세스 사전에는 해싱이 포함됩니다. 사전은 사실 해시 맵입니다. 해시 맵에서 get/set의 최악의 경우time complexity는 O(n)입니다.

    슬롯은 개체의 크기를 줄이는 특수 메커니즘을 제공합니다. 개체에 대한 메모리 최적화의 개념입니다.

    Python의 모든 객체에는 속성 추가를 허용하는 동적 사전이 포함되어 있습니다. 모든 인스턴스 개체에 대해 더 많은 공간을 사용하고 많은 RAM을 낭비하는 사전 인스턴스를 갖게 됩니다. Python에는 모든 속성을 저장할 객체를 생성하는 동안 정적 양의 메모리를 할당하는 기본 기능이 없습니다.
    __slots__를 사용하면 고정된 양의 속성에 공간을 할당하여 공간 낭비를 줄이고 프로그램 속도를 높일 수 있습니다.

    슬롯을 생성하려면 데이터 클래스를 사용하는 경우 __slots__ 필드 또는 slots=True를 추가하기만 하면 됩니다.

    class PersonSlot:
         __slots__ = ["first_name", "last_name"]
         def __init__ (self, first_name: str, last_name: str):
             self.first_name = first_name
             self.last_name = last_name
    
    if __name__ == " __main__":
         person = Person("Chidozie", "Okafor")
         print(person. __dict__ )
      {'first_name': 'Chidozie', 'last_name': 'Okafor'}
        print(Person. __dict__ )
    {' __module__': ' __main__', ' __slots__': ['first_name', 'last_name'], ' __init__': <function __init__ at 0x10432b140>, ' __doc__': None}
    


    변수 이름의 반복을 피하기 위해 데이터 클래스를 사용하여 자동으로 슬롯을 생성하는 클래스를 만들 수 있습니다.

    from dataclasses import dataclass
    
    @dataclass(slots=True)
    class PersonSlot:
          first_name: str
          last_name: str
    
    if __name__ == " __main__":
       person = PersonSlot("Chidozie", "Okafor")
       print(person. __dict__ )
       print(PersonSlot. __dict__ )
    


    슬롯 사용의 이점:


  • 슬롯이 __dict__보다 빠릅니다.
  • 슬롯이 메모리 효율성이 더 높습니다.
  • 슬롯이 더 안전합니다.
  • 슬롯이 더 편리합니다.
  • 슬롯이 더 읽기 쉽습니다.
  • 슬롯이 더 효율적입니다.

  • 슬롯 사용의 단점:


  • 슬롯이 다중 상속 및 혼합과 호환되지 않습니다.
  • 슬롯이 메타클래스와 호환되지 않습니다.
  • 슬롯이 ABC와 호환되지 않습니다.
  • 슬롯은 절임과 호환되지 않습니다.
  • 슬롯이 복사와 호환되지 않습니다.
  • 슬롯이 deepcopy와 호환되지 않습니다.

  • 슬롯이 일반 사전과 비교하여 얼마나 빠른지 봅시다.




    import timeit
    from dataclasses import dataclass
    from functools import partial
    
    @dataclass(slots=False)
    class Person:
        first_name : str
        last_name: str
    
    @dataclass(slots=True)
    class PersonSlot:
        first_name : str
        last_name : str
    
    def get_set_delete(person: Person | PersonSlot):
         person.first_name = "Raphael"
         _ = person.first_name
         del person.first_name
    
    def get_percentage_of_performance():
        person = Person("Chidozie", "Okafor")
        person_slot = PersonSlot("Chidozie", "Okafor")
        no_slots = min(timeit.repeat(partial(get_set_delete, person), number=100, repeat=3))
        slots = min(timeit.repeat(partial(get_set_delete, person_slot), number=100, repeat=3))
        print(f"No Slots: {no_slots}") No Slots: 3.3914000596269034e-05
    
    print(f"Slots: {slots}") Slots: 1.8151000404031947e-05
        print(f"Percentage of performance: {(slots / no_slots) * 100}") Percentage of performance: 53.520670180175635
    
    if __name__ == " __main__":
        get_percentage_of_performance()
    


    코드 속도를 향상시키기 위해 슬롯으로 할 수 있는 일이 너무 많습니다. 가능한 한 많이 시도하고 다른 사람들과 공유하십시오.

    행복한 코딩!!!!

    좋은 웹페이지 즐겨찾기