입출력 처리
- str() 함수는 사람이 읽기 쉬운 형식으로, repr() 함수는 인터프리터가 이해하기 쉬운 형식으로 데이터를 표현합니다.
- rjust()는 오른쪽 정렬, ljust()는 왼쪽 정렬, center()는 가운데 정렬을 수행합니다. zfill()은 지정된 길이에 맞게 문자열 앞에 0을 채웁니다.
네임스페이스
- 네임스페이스는 이름과 객체 간의 매핑 관계를 의미합니다.
- 네임스페이스는 딕셔너리를 사용하여 구현됩니다.
- 다른 네임스페이스에서 동일한 이름은 서로 독립적입니다.
- 다음과 같은 네임스페이스가 존재하며, 검색 순서는 다음과 같습니다:
- 가장 안쪽 함수의 지역 이름
- 바깥쪽 함수의 전역이 아닌 비지역 이름
- 모듈의 전역 이름
- 언어의 내장 이름
def scope_demo():
def do_local():
value = "지역 값"
def do_nonlocal():
nonlocal value
value = "비지역 값"
def do_global():
global value
value = "전역 값"
value = "테스트 값"
do_local()
print("지역 할당 후:", value)
do_nonlocal()
print("비지역 할당 후:", value)
do_global()
print("전역 할당 후:", value)
scope_demo()
print("전역 범위에서:", value)
지역 할당 후: 테스트 값
비지역 할당 후: 비지역 값
전역 할당 후: 비지역 값
전역 범위에서: 전역 값
클래스
- 클래스 멤버 기본값은 public이며, 하위 클래스에서 메서드를 모두 오버라이드(재정의)할 수 있습니다.
- 클래스 이름 자체가 객체입니다.
- 클래스 메서드의 첫 번째 매개변수는 일반적으로 클래스 인스턴스 자신을 가리키는 self 매개변수입니다.
- 메서드 이름 자체가 객체입니다.
- 클래스 변수와 인스턴스 변수가 존재합니다.
- 적어두 개의 밑줄로 시작하는 변수는 private 변수입니다.
- 내장 타입도 기본 클래스로 사용할 수 있습니다.
- 다중 상속이 가능합니다.
>> class SampleClass:
"""간단한 클래스 예제"""
counter = 12345
def __init__(self):
self.collection = []
def greeting(self):
return '안녕하세요 세계'
>>> SampleClass.counter
12345
>>> SampleClass.greeting(None)
'안녕하세요 세계'
>>> SampleClass.__doc__
'간단한 클래스 예제'
>>> instance = SampleClass()
>>> instance.counter
12345
>>> instance.greeting()
'안녕하세요 세계'
>>> greeting_method = instance.greeting
>>> print(greeting_method())
안녕하세요 세계
>>> class ComplexNumber:
def __init__(self, real, imag):
self.r = real
self.i = imag
>>> num = ComplexNumber(3.0, -4.5)
>>> num.r, num.i
(3.0, -4.5)
데이터 속성과 메서드
- 클래스 멤버에는 데이터 속성과 메서드가 포함됩니다.
위 예제에서
SampleClass는 클래스이며, SampleClass.counter는 클래스 객체의 데이터 속성이고, SampleClass.greeting은 함수 객체(function object)입니다.
instance는 클래스의 인스턴스이며, instance.collection은 인스턴스의 데이터 속성이고, instance.greeting은 메서드 객체(method object)입니다.
- 메서드의 첫 번째(숨겨진) 매개변수는 클래스 인스턴스 객체입니다.
instance.greeting()은 실제로 greeting(instance)와 동일합니다.
- 인스턴스 객체의 속성과 메서드는 인스턴스 객체 소유이며, 클래스 객체의 속성과 메서드는 클래스의 모든 인스턴스가 공유합니다.
>> class Animal:
species = 'mammal' # 모든 인스턴스가 공유하는 클래스 변수
def __init__(self, name):
self.name = name # 각 인스턴스에 고유한 인스턴스 변수
>>> pet1 = Animal('Whiskers')
>>> pet2 = Animal('Buddy')
>>> pet1.species # 모든 동물이 공유
'mammal'
>>> pet2.species # 모든 동물이 공유
'mammal'
>>> pet1.name # pet1에 고유
'Whiskers'
>>> pet2.name # pet2에 고유
'Buddy'
>>> class Pet:
def __init__(self, name):
self.name = name
self.abilities = [] # 각 펫마다 새로운 빈 리스트 생성
def add_ability(self, ability):
self.abilities.append(ability)
>>> cat = Pet('Whiskers')
>>> dog = Pet('Buddy')
>>> cat.add_ability('meow')
>>> dog.add_ability('bark')
>>> cat.abilities
['meow']
>>> dog.abilities
['bark']
- 속성명과 메서드명이 충돌할 경우 속성명이 우선합니다.
- 인스턴스 객체는 클래스 외부에 자신만의 고유 속성을 추가할 수 있습니다.
- 메서드는 클래스 외부에서 정의할 수 있습니다.
# 클래스 외부에서 정의된 함수
def calculate(self, a, b):
return min(a, a+b)
class Calculator:
operation = calculate
def greet(self):
return '안녕하세요'
hello = greet
- 메서드에서 다른 메서드를 호출할 수 있습니다.
class Container:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
def add_twice(self, item):
self.add_item(item)
self.add_item(item)
- 인스턴스 객체는 자신의 클래스 객체를 object.**class**로 참조할 수 있습니다.
- 빈 클래스 정의는 다른 언어의 레코드와 구조체를 모방하는 데 사용할 수 있습니다.
class Employee:
pass
worker = Employee() # 빈 직원 레코드 생성
# 레코드 필드 채우기
worker.name = '홍길동'
worker.department = '개발팀'
worker.salary = 5000
상속
- 상속 구문은 `class DerivedClassName(modname.BaseClassName):` 입니다.
- 기본 클래스의 메서드는 하위 클래스에서 오버라이드(재정의)할 수 있습니다.
- 하위 클래스는 `BaseClassName.methodname(self, arguments)`를 통해 기본 클래스의 (동일한 이름의) 메서드를 호출할 수 있습니다.
- isinstance()는 클래스의 인스턴스인지 확인합니다
obj가 int 타입이나 그 하위 클래스의 인스턴스라면 isinstance(obj, int) == True가 성립합니다.
- issubclass()는 클래스의 하위 클래스인지 확인합니다
issubclass(bool, int) == True
issubclass(float, int) == False
- 다중 상속 구문은 `class DerivedClassName(Base1, Base2, Base3):` 입니다.
반복자
반복자 사용 사례
>> for item in [1, 2, 3]:
print(item)
1
2
3
>>> for item in (1, 2, 3):
print(item)
1
2
3
>>> for key in {'one':1, 'two':2}:
print(key)
one
two
>>> for char in "123":
print(char)
1
2
3
>>> for line in open("myfile.txt"):
print(line, end='')
- for 루프가 컨테이너를 반복할 수 있는 것은 컨테이너가 반복자 인터페이스를 구현했기 때문입니다.
- for 루프는 먼저 iter(container)를 호출하여 반복자 객체 iterator를 얻습니다.
- for 루프는 next(iterator)를 반복적으로 호출하여 컨테이너 container의 요소를 가져옵니다.
- 컨테이너의 요소가 모두 반복되면 next(iterator)는 StopIteration 예외를 발생시키고 for 루프가 종료됩니다.
반복자 세부사항
>> text = 'abc'
> iterator = iter(text)
>>> iterator
>>> next(iterator)
'a'
>>> next(iterator)
'b'
>>> next(iterator)
'c'
>>> next(iterator)
Traceback (most recent call last):
File "", line 1, in <module>
next(iterator)
StopIteration
- iter(container)는 container의 __iter__ 메서드를 호출합니다.
이 메서드는 iterator 객체를 반환합니다.
- next(iterator)는 iterator의 __next__ 메서드를 호출합니다.
이 메서드는 다음 요소를 반환하거나 StopIteration 예외를 발생시킵니다.
- 일반적으로 container와 iterator는 동일한 객체입니다.
반복자 예제
>> class ReverseIterator:
"""시퀀스를 역순으로 순회하는 반복자"""
def __init__(self, data):
self.data = data
self.position = len(data)
def __iter__(self):
return self
def __next__(self):
if self.position == 0:
raise StopIteration
self.position = self.position - 1
return self.data[self.position]
>>> reversed_text = ReverseIterator('word')
>>> iter(reversed_text)
<__main__.ReverseIterator object at 0x02C95670>
>>> for char in reversed_text:
print(char)
d
r
o
w
제너레이터
- 제너레이터 함수는 yield를 사용하여 자동으로 반복자 인터페이스를 구현합니다.
>> def reverse_sequence(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse_sequence('flow'):
print(char)
w
o
l
f
제너레이터 표현식
- 제너레이터 표현식은 소괄호와 해석식을 사용하여 자동으로 반복자 인터페이스를 생성합니다.
>> sum(i*i for i in range(10)) # 제곱의 합
285
>>> list1 = [10, 20, 30]
>>> list2 = [7, 5, 3]
>>> sum(x*y for x,y in zip(list1, list2)) # 내적
260
>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
>>> unique_words = set(word for line in page for word in line.split())
>>> top_student = max((student.score, student.name) for student in graduates)
>>> data = 'word'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['d', 'r', 'o', 'w']