Python-Special Methods

Python-Special Methods 클래스에 특별한 기능을 부여하는 특수한 메소드. 언더스코어 두 개로 둘러싸인 이름을 가지며, 파이썬 인터프리터에 의해 특정 상황에서 자동으로 호출된다. 객체 생성 및 초기화 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Example: def __new__(cls, *args, **kwargs): # 객체 생성 전에 호출되는 메서드 print("1. __new__ 호출: 객체 생성") # 실제 객체 생성 instance = super().__new__(cls) return instance def __init__(self, value): # 객체 초기화 메서드 print("2. __init__ 호출: 객체 초기화") self.value = value def __del__(self): # 객체가 소멸될 때 호출되는 메서드 print("3. __del__ 호출: 객체 소멸") # 사용 예시 obj = Example(10) # __new__와 __init__ 호출 del obj # __del__ 호출 객체 표현 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): # 사용자 친화적인 문자열 표현 return f"{self.name} ({self.age}세)" def __repr__(self): # 개발자를 위한 상세한 문자열 표현 return f"Person(name='{self.name}', age={self.age})" def __format__(self, format_spec): # 형식화된 문자열 표현 if format_spec == 'brief': return f"{self.name}" return str(self) # 사용 예시 person = Person("홍길동", 30) print(str(person)) # __str__ 호출 print(repr(person)) # __repr__ 호출 print(format(person, 'brief')) # __format__ 호출 __str__와 __repr__의 차이 특징 str repr 목적 사용자 친화적 출력 개발자 친화적 출력 사용 print() 함수 디버깅, 개발 상세도 간단한 설명 상세한 정보 형식 읽기 쉬운 형식 정확한 정보 포함 연산자 오버로딩 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): # + 연산자 return Vector(self.x + other.x, self.y + other.y) def __sub__(self, other): # - 연산자 return Vector(self.x - other.x, self.y - other.y) def __mul__(self, scalar): # * 연산자 return Vector(self.x * scalar, self.y * scalar) def __truediv__(self, scalar): # / 연산자 return Vector(self.x / scalar, self.y / scalar) def __floordiv__(self, scalar): # // 연산자 return Vector(self.x // scalar, self.y // scalar) def __mod__(self, scalar): # % 연산자 return Vector(self.x % scalar, self.y % scalar) def __pow__(self, power): # ** 연산자 return Vector(self.x ** power, self.y ** power) def __lshift__(self, other): # << 연산자 return self.x << other.x, self.y << other.y def __rshift__(self, other): # >> 연산자 return self.x >> other.x, self.y >> other.y def __and__(self, other): # & 연산자 return self.x & other.x, self.y & other.y def __or__(self, other): # | 연산자 return self.x | other.x, self.y | other.y def __xor__(self, other): # ^ 연산자 return self.x ^ other.x, self.y ^ other.y v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # 벡터 덧셈 print(v1 * 2) # 벡터 스칼라 곱 단항 연산자 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Number: def __init__(self, value): self.value = value def __pos__(self): # 단항 + 연산자 return Number(+self.value) def __neg__(self): # 단항 - 연산자 return Number(-self.value) def __abs__(self): # abs() 함수 return Number(abs(self.value)) def __invert__(self): # ~ 연산자 return Number(~self.value) n = Number(5) print(abs(n).value) # 절대값 print((~n).value) # 비트 반전 비교 연산자 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Temperature: def __init__(self, celsius): self.celsius = celsius def __eq__(self, other): # == 연산자 return self.celsius == other.celsius def __ne__(self, other): # != 연산자 return self.celsius != other.celsius def __lt__(self, other): # < 연산자 return self.celsius < other.celsius def __le__(self, other): # <= 연산자 return self.celsius <= other.celsius def __gt__(self, other): # > 연산자 return self.celsius > other.celsius def __ge__(self, other): # >= 연산자 return self.celsius >= other.celsius t1 = Temperature(20) t2 = Temperature(25) print(t1 < t2) # 온도 비교 컨테이너 메소드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class CustomList: def __init__(self, items): self.items = items def __len__(self): # len() 함수 return len(self.items) def __getitem__(self, index): # 인덱싱 return self.items[index] def __setitem__(self, index, value): # 인덱스로 값 설정 self.items[index] = value def __delitem__(self, index): # 인덱스로 항목 삭제 del self.items[index] def __iter__(self): # 이터레이션 return iter(self.items) def __next__(self): # 다음 항목 반환 if not self.items: raise StopIteration return self.items.pop(0) def __contains__(self, item): # in 연산자 return item in self.items cl = CustomList([1, 2, 3, 4, 5]) print(len(cl)) # 길이 print(cl[2]) # 인덱싱 print(3 in cl) # 포함 여부 속성 접근 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class DynamicAttributes: def __init__(self): self._attributes = {} def __getattr__(self, name): # 존재하지 않는 속성 접근 return self._attributes.get(name, None) def __setattr__(self, name, value): # 속성 설정 if name == '_attributes': super().__setattr__(name, value) else: self._attributes[name] = value def __delattr__(self, name): # 속성 삭제 del self._attributes[name] def __getattribute__(self, name): # 모든 속성 접근 시 호출 print(f"Accessing attribute: {name}") return super().__getattribute__(name) da = DynamicAttributes() da.new_attr = 42 print(da.new_attr) del da.new_attr 호출 가능 객체 1 2 3 4 5 6 7 class Adder: def __call__(self, x, y): # 객체를 함수처럼 호출 return x + y add = Adder() print(add(3, 4)) # 객체를 함수처럼 사용 컨텍스트 관리 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class FileManager: def __init__(self, filename): self.filename = filename def __enter__(self): # with 문 진입 시 호출 self.file = open(self.filename, 'w') return self.file def __exit__(self, exc_type, exc_value, traceback): # with 문 종료 시 호출 self.file.close() with FileManager('test.txt') as f: f.write('Hello, World!') 피클링 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pickle class Picklable: def __init__(self, value): self.value = value def __reduce__(self): # 객체의 직렬화 방법 정의 return (self.__class__, (self.value,)) obj = Picklable(42) pickled = pickle.dumps(obj) unpickled = pickle.loads(pickled) print(unpickled.value) 기타 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class CustomNumber: def __init__(self, value): self.value = value def __hash__(self): # hash() 함수 return hash(self.value) def __bool__(self): # bool() 함수 return bool(self.value) def __index__(self): # 정수형 변환 return int(self.value) cn = CustomNumber(42) print(hash(cn)) print(bool(cn)) print(list(range(cn))[0]) # __index__ 사용 참고 및 출처

November 25, 2024 · 6 min · Me

Python - Iterators

Python - Iterators 데이터 컬렉션의 요소들을 순차적으로 접근할 수 있게 해주는 객체 이터레이터의 기능과 역할 데이터 스트림에서 한 번에 하나의 항목을 반환 현재 항목과 방문한 항목을 추적 컨테이너의 요소에 순차적으로 접근 메모리를 효율적으로 사용 이터레이터의 특징 __iter__() 및 __next__() 메서드를 구현하여 이터레이터 프로토콜을 따름 next() 함수를 사용하여 다음 요소에 접근 모든 요소를 순회한 후 StopIteration 예외 발생 지연 평가(lazy evaluation)를 지원하여 필요한 요소만 생성 활용 대용량 파일 처리 데이터베이스 쿼리 결과 처리 스트리밍 데이터 처리 메모리 효율적인 데이터 처리 실시간 데이터 생성 이터레이터의 종류 기본 이터레이터 가장 일반적인 형태의 이터레이터. __iter__와 __next__ 메서드를 구현하여 만든다. ...

November 25, 2024 · 4 min · Me

name mangling

Name Mangling 파이썬에서 “name mangling"은 클래스 내부의 속성이나 메서드의 이름을 변경하는 기능이다. 이 기능은 주로 정보 은닉과 캡슐화를 위해 사용된다. 네임 맹글링의 작동 방식 더블 언더스코어 사용: 클래스 내에서 속성이나 메서드 이름 앞에 두 개의 언더스코어(__)를 붙이면 자동으로 네임 맹글링이 적용된다. 1 2 3 4 5 6 7 8 9 10 11 class Person: def __init__(self): self.__name = "김철수" # 실제로는 '_Person__name'으로 변환됨 def __private_method(self): # 실제로는 '_Person__private_method'로 변환됨 return "비공개 메서드" person = Person() print(dir(person)) # 실제 변환된 이름을 확인할 수 있음 print(person.__name) # AttributeError 발생 print(person._Person__name) # 김철수 출력 이름 변환 규칙: ...

November 25, 2024 · 2 min · Me

Python Super

Python Super super()는 상속 관계에서 부모 클래스의 메서드를 호출하는 데 사용되는 중요한 도구. 부모 클래스(슈퍼클래스)의 메서드를 호출할 때 사용된다. 주로 자식 클래스에서 부모 클래스의 메서드를 확장하거나 재정의할 때 활용된다. 사용 예제: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Animal: def __init__(self, name): self.name = name def speak(self): return f"{self.name} makes a sound" class Dog(Animal): def __init__(self, name, breed): # 부모 클래스의 __init__ 메서드 호출 super().__init__(name) self.breed = breed def speak(self): # 부모 클래스의 speak 메서드를 확장 base_sound = super().speak() return f"{base_sound} - specifically, a woof!" # 사용 예시 my_dog = Dog("Rex", "Golden Retriever") print(my_dog.speak()) # 출력: "Rex makes a sound - specifically, a woof!" 특징 부모 클래스 참조: super()는 현재 클래스의 부모 클래스를 참조한다. 메서드 연결: 부모 클래스의 메서드에 접근하여 호출할 수 있게 한다. 동적 결정: 런타임에 메서드 호출을 결정한다. MRO(Method Resolution Order) 활용: 다중 상속 시 메서드 해석 순서를 따른다. 장점 코드 재사용: 부모 클래스의 코드를 재사용하여 중복을 줄인다. 유연성: 부모 클래스의 구현을 변경해도 자식 클래스에서 수정할 필요가 없다. 다중 상속 지원: 복잡한 상속 구조에서도 적절한 부모 메서드를 호출할 수 있다. 단점 복잡성: 다중 상속 시 상속 구조가 복잡해질 수 있다. 예상치 못한 동작: 상속 계층에 따라 의도하지 않은 메서드가 호출될 수 있다. 주요 사용 방법 super().init(): 부모 클래스의 생성자를 호출한다. super().method_name(): 부모 클래스의 특정 메서드를 호출한다. super()의 고급 기능과 특징 다중 상속에서의 활용 super()는 다중 상속 상황에서 메서드 해결 순서(MRO)를 따라 적절한 메서드를 찾아준다: ...

November 25, 2024 · 4 min · Me

Method Resolution Order (MRO)

Method Resolution Order (MRO) 파이썬에서 클래스의 상속 관계에서 메서드를 찾는 순서를 정의하는 규칙으로 자식과 부모 클래스를 모두 포함하여 메서드의 실행 순서를 정한다. 이는 특히 다중 상속이 있을 때 매우 중요하다. 파이썬은 C3 선형화 알고리즘을 사용하여 이 순서를 결정한다. MRO와 관련된 문제가 발생하면 __mro__ 속성을 통해 메서드 해결 순서를 확인하고, 필요한 경우 클래스 계층 구조를 재설계하거나 명시적인 메서드 호출을 사용하여 문제를 해결할 수 있다. 동작 방식 호출된 자식 클래스를 먼저 확인한다. 그 다음 상속된 클래스들을 나열한 순서대로 확인한다. 우선순위 자식 클래스 부모 클래스 (먼저 상속받을수록 우선순위가 높음) 부모 클래스의 부모 클래스 (존재하는 경우) object 클래스 (최상위) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class A: def method(self): print("A's method") class B(A): def method(self): print("B's method") class C(A): def method(self): print("C's method") class D(B, C): pass # MRO 확인 print(D.__mro__) # 출력: (<class '__main__.D'>, <class '__main__.B'>, # <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) d = D() d.method() # B's method가 출력됨 다이아몬드 문제와 MRO 다이아몬드 문제는 다중 상속에서 발생할 수 있는 고전적인 문제. 파이썬의 MRO는 이 문제를 해결하는 방법을 제공한다. ...

November 25, 2024 · 3 min · Me