Python 클래스·인스턴스·descriptor
파이썬 클래스 · Python 객체 지향
클래스는 인스턴스의 상태와 동작을 정의하는 객체이며 인스턴스는 그 클래스를 바탕으로 만들어진 개별 객체이다. 속성 조회·메서드 바인딩·상속·descriptor 규칙이 실제로 어떤 값과 함수를 선택하는지 결정한다.
밑줄 용어에 마우스를 올리거나, 키보드로 선택하거나, 터치하면 설명을 볼 수 있습니다.
01무엇이고, 어떤 일을 하나
- 관련 상태와 검증·동작을 하나의 책임으로 묶는다.
- 인스턴스별 상태와 클래스가 공유하는 속성을 구분한다.
- property·메서드·상속으로 접근 규칙과 협력을 표현한다.
02어떤 순서로 동작하나
- 클래스 정의
본문을 실행해 이름 공간을 만들고 클래스 객체를 생성한다.
- 인스턴스 생성
클래스 호출에서 __new__가 생성에 관여하고 일반적인 경우 __init__가 를 초기화한다.
- 속성 조회
descriptor·인스턴스 사전·클래스 검색 규칙에 따라 속성을 찾고 일반 함수는 인스턴스와 결합된 가 될 수 있다.
- 동작과 변경
메서드가 를 통해 상태를 읽고 바꾸며 property는 접근 문법에 검증·변환을 연결한다.
03먼저 알아둘 용어와 구성요소
- 의 문은 내부 이름 공간에서 정의를 실행하고 클래스 객체를 만든다.
- __new__가 객체 생성에 관여하고, 일반적인 경우 새 인스턴스에 대해 __init__가 초기화를 수행한다.
- 각 인스턴스에 필요한 상태는 .name처럼 해당 인스턴스에 저장한다.
- 클래스 안의 일반 함수를 인스턴스에서 가져오면 인스턴스와 함수가 연결된 가 된다.
- 는 예약 키워드가 아니라 첫 매개변수의 관례적 이름이며 메서드가 자신을 호출한 인스턴스에 접근할 통로다. 를 빼고 인자 없는 함수처럼 정의하면 호출할 때 자동 전달된 인스턴스를 받을 수 없어 오류가 날 수 있다.
- 읽기 우선순위에서 __get__이 있고 __set__ 또는 __delete__를 제공하는 descriptor는 같은 이름의 인스턴스 사전 항목보다 우선할 수 있다. 읽기와 대입의 규칙을 나누어 적용한다.
장비 클래스로 공통 종류와 개별 주소를 나누기
장비 객체를 생성할 때 생기는 와 메서드 호출의 를 실제 클래스 코드에 연결한다.
실습 구성과 전제
- 사진에는 Server와 Network 클래스, 생성자, 출력 메서드가 함께 있다. 인증 필드는 재구성 코드에서 제거하고 문서용 주소만 사용한다.
- 핵심 구조가 한 화면에 모여 있어 같은 사진을 여러 단계에 중복 배치하지 않는다. 아래 출력은 재구성 코드의 예상 결과다.
클래스 몸체와 생성자의 대입 위치를 구별한다
- 사진의 category는 클래스 수준에 정의되고 __init__은 전달받은 주소를 .ip에 저장한다. 전자는 종류의 공통 기본값, 후자는 생성한 각 객체의 상태를 표현한다.
- Server(...)를 두 번 호출하면 별도 인스턴스가 생긴다. 는 특정 예약 키워드가 아니라 메서드에서 관례적으로 사용하는 첫 인자 이름이며, 호출 시 인스턴스가 전달된다.
원본 크기로 보기 ↗- Server와 Network에 각각 category와 __init__ 메서드가 정의되어 있다.
- 생성자에서 self.ip를 설정하고 view가 속성을 출력하며, 아래에서 여러 객체를 리스트에 넣는 구성이 보인다.
확인 기준같은 클래스에서 만들었다는 이유로 모든 속성이 하나의 공용 저장소에 들어간다고 해석하지 않는다. 클래스 대입과 대입 위치를 대조한다.
두 객체를 만든 뒤 한 객체만 변경한다
- 재구성 코드에서 a와 b의 ip는 각 인스턴스 사전에 저장된다. a.ip를 새 문자열로 바꿔도 b.ip가 자동 변경되지 않는다.
- category는 여기서 불변 문자열을 공통으로 읽는다. 클래스 속성에 가변 list를 두고 여러 인스턴스가 그 list를 수정하는 경우와 구분한다.
class Server: category = "server" def __init__(self, ip): self.ip = ip def view(self): return f"{self.category}: {self.ip}" a = Server("192.0.2.10") b = Server("192.0.2.11") a.ip = "192.0.2.20" print(a.view()) # server: 192.0.2.20 print(b.view()) # server: 192.0.2.11자격 정보 없이 주소와 종류만 남긴 재구성 예시다.
확인 기준두 인스턴스의 주소 출력이 각각 다르고, a의 변경 뒤 b가 유지되는지 확인한다. 사진의 계정·암호 필드를 복사할 필요는 없다.
bound method와 속성 조회 결과를 연결한다
- a.view()는 a에 묶인 메서드를 호출한다. 이 예시에서는 Server.view(a)와 같은 인스턴스를 전달하므로 동일 문자열을 반환한다.
- vars(a)에는 인스턴스에 설정한 ip가 보이고 category는 클래스 쪽에서 찾는다. a.category를 새로 대입하면 그 인스턴스의 이름이 클래스 기본값을 가릴 수 있다.
print(vars(a)) # {'ip': '192.0.2.20'} print(a.view() == Server.view(a)) # True print(Server.category, b.category) # server server앞의 재구성 객체를 이어 사용한 예상 출력이다.
확인 기준인스턴스 사전에 없는 속성도 클래스에서 조회될 수 있다. vars 출력에 없다는 이유만으로 속성이 존재하지 않는다고 단정하지 않는다.
실습에서 확인한 동작 원리
- 클래스는 공통 속성과 동작을 정의하고, 생성자의 대입은 각 인스턴스의 상태를 만든다.
- 메서드 호출은 객체 상태를 인자로 전달하는 구조이므로 데이터와 동작의 연결을 추적할 수 있다.
동작·명령 참고 문서
04예제로 따라가기
- 에 items=[]를 하나 두면 여러 인스턴스가 같은 리스트를 볼 수 있다. 인스턴스마다 별도 목록이 필요하면 초기화에서 .items=[]를 만든다.
- device.label()은 일반적인 메서드에서 Device.label(device)와 같은 인자 관계를 가지므로 는 자동 전달받을 첫 인자의 관례적 이름이다.
- setter 없는 property에 대입하면 인스턴스 사전에 같은 이름을 두는 것과 달리 대입이 거부될 수 있다.
05혼동하기 쉬운 점과 확인 기준
- 상속을 쓰는 것만으로 객체 설계가 좋아지는 것은 아니다. 공유 상태·변경 책임·외부 자원의 수명을 실제 사용 관계에 맞게 나눈다.
- __init__는 다른 객체를 반환하는 공장 함수가 아니라 초기화 메서드이며 일반적인 계약에서 None을 반환해야 한다.
06상세 노트 · 실습 자료
헤더 구조, 설정 예시, 수치 계산과 수업 캡처는 아래 노트에서 이어집니다.
함께 보는 학습 자료
아래 공식 자료를 본문의 개념·예제와 함께 읽어 보세요. 자료별로 확인할 위치와 관찰할 내용을 적었습니다.
Python 클래스·인스턴스 변수 실습
and Instance Variables의 공유 리스트 예제를 먼저 읽는다. 같은 클래스의 두 인스턴스에서 메서드를 호출할 때 어느 리스트를 수정하는지 손으로 추적한 뒤 초기화 방식과 비교한다.
- 클래스 변수와 인스턴스 변수의 저장 위치
- 를 받는 메서드 바인딩
- 가변 클래스 속성의 공유 결과
Descriptor의 실제 속성 조회 우선순위
Invocation from an instance의 등가 코드를 읽고 property와 동일 이름의 __dict__ 항목을 대입해 본다. __get__ 존재 여부와 판정이 별개 검사임을 코드 순서로 확인한다.
- →인스턴스 사전→비데이터 descriptor 순서
- 읽기 전용 property가 대입을 거부하는 원리
- 클래스 속성 조회와 인스턴스 조회의 차이
공식 문서 · 표준
기초 개념과 동작 설명을 대조한 자료입니다. 제품 버전과 실제 설정에 따른 차이는 본문 및 원문에서 확인하세요.