1. 객체 지향 프로그래밍
다른 프로그래밍 언어와 같이 클래스를 사용할 수 있고 클래스 이름은 파스칼 케이스로 클래스의 이름을 표기하면 된다. 크래스는 0 개 이상의 멤버 함수를 포함하며 모든 멤버 함수의 첫 번째 인자는 해당 클래스의 인스턴스를 의미하는 self로 정의해야 한다.
메서드의 이름이 언더 바로 시작하는 경우, 클래스 밖에서 호출을 하면 안되는 private 메서드를 의미한다. init , repr 등 이름의 앞 뒤로 언더바가 두개 씩 추가된 메서드는 dunder(double_UNDERscore)메서드라고 부르며 특별한 기능을 가지고 있다.
또한 부모 클래스에서 기느을 상속받을 수 있는 서브클래스를 종종 사용할 수 있다.
class CountingClicker:
def __init__(self, count = 0)
self.count = count
def __repr__(self, num_times = 1):
return f"CountingClicker(count={self.count})"
def click(self, num_times = 1):
self.count += num_times
def read(self):
return self.count
def reset(self):
self.count = 0
class NoResetClicker(CountingClicker):
def reset(self):
pass
clicker2 = NoResetClicker()
assert clicker2.read() == 0
clicekr2.reset()
assert clicker2.read() == 1, "reset shouldn't do anything"
2. 이터레이너와 제너레이터
이터레이터는 반복가능한 객체이고, 제너레이터는 이터레이터의 한 종류로 모든 데이터의 위치를 가지지 않고 yeild를 통하여 위치를 정하여 반복하는 객체이다. 주로 yield를 사용하고 이를 사용하는 이유는 메모리를 효율적으로 사용하기 위해서이다.
def generate_range(n):
i = 0
while i < n:
yeild i
i += 1
for i in generate_range(10):
print(f"i: {i}")
사실 range 자체가 제너레이터로 만들어졌기 때문에 이렇게 따로 만들 필요는 없다.
종종 리스트나 제너레이터에서 항목을 하나씩 확인해 볼 경우, 항목의 순서(index)를 반환하고 싶을 때가 있다. 이럴 때는 enumerate 함수를 사용 하면 된다.
for i, name in enumerate(names):
print(f"name {i} is {name}")
3. 난수 생성
주로 random 모듈을 사용, 만약 수도 랜덤(pseudo random)한(결정론적으로 동일한) 난수를 계속 사용하고 싶다면 random.seed를 통해 매번 고정된 난수를 설정하면 된다.
import random
random.seed(10)
four_uniform_randoms = [random.random() for _ in range(4)]
인자가 1개 혹은 2개인 random.randrange메서드를 사용하면 range()에 해당하는 구간 안에서 난수를 생성할 수 있다.
random.randomrange(10)
random.randomrange(3, 6)
- random.shuffle은 리스트의 항목을 임의 순서대로 재정렬 해준다.
- random.choice는 리스트의 리스트에서 임의의 항목을 선택한다.
- random.sample을 사용하면 리스트에서 중복이 허용되지 않는 임의의 표본 리스트를 만들 수 있다.
만약 중복이 혀용되는 임의의 표본 리스트를 만들고 싶다면 random.choice 메서드를 여러번 사용하면 된다.
four_with_replacemeont = [random.choice(range(10)) for _ in range(4)]
print(four_with_placement)
4. 정규표현식
파이썬도 다른 프로그래밍 언어와 같이 "import re" re라이브러리를 통해 정규표현식을 사용하여 문자열을 찾을 수 있다.
5. zip과 인자 언패킹
두 개 이상의 리스트를 서로 묶어 주고 싶을 때 zip은 여러개의 리스트를 서로 사응하는 항목의 튜플로 구성된 리스트로 변환한다. 묶인 리스트는 다시 풀어 줄 수도 있다.
list1 = ['a', 'b', 'c']
list2 = [1, 2, 3]
[pair for pair in zip(list, list2)]
letters, numbers = zip(*pairs)
별표(*)는 인자 언패킹(argument unpacking)을 할 때 사용되는 문법으로, 이를 사용하면 pairs 안의 항목들을 zip함수에 개별적인 인자로 전달해준다.
6. args 와 kwargs
특정 함수 f를 입력하면 f의 결과를 두 배로 만드는 함수를 반환해 주는 고차 함수를 만든다면,
def double(f):
def g(x):
return 2 * f(x)
return g
def f1(x):
return x + 1
g = doubler(f1)
assert (g3) == 8
위 와 같은 방식으로 사용할 수 있지만, 두 개 이상의 인자를 받는 함수의 경우에는 다음과 같은 문제가 발생한다.
def f2(x, y):
return x + y
g = doubler(f2)
try:
g(1, 2)
except TypeError:
print("as defined, g only takes one argument")
위의 문제를 해결하기 위해 임의의 수의 인자를 받는 함수를 만들어 줘야 한다. 앞서 설명한 인자 언패킹을 사용하면 마법같이 임의의 수의 인자를 받는 함수를 만들 수 있다.
def magic(*args, **kwargs):
print("unnamed args:", args)
print("keword args:", kwargs)
magic(1, 2, key="word", key2="word2"
다음과 같은 결과가 출력된다.
unnamed args:(1, 2)
keword args: {'key': 'word', 'key2':'word2')
위에서 args는 이름이 ㅇ벗는 인자로 구성된 튜플이며, kwargs는 이름이 주어진 인자로 구성된 딕셔너리이다. 반대로, 정해진 수의 인자가 있는 함수를 호출할 때도 리스트나 딕셔너리로 인자를 전달할 수 있다.
def other_way_magin(x, y, z):
return x + y + z
x_y_list = [1,2]
z_dict = {"z": 3}
assert other_way_magic(*x_y_list, **z_dict) == 6, "1 + 2 + 3 should be 6"
코드의 가독성을 위해 함수에서 필요한 인자를 모두 표시해주는 것이 좋고, 꼭 필요한 경우에만 args, kwargs를 사용해야 한다.
7. 타입 어노테이션
최근 파이썬도 타입을 명시하기 시작했다. 아무런 기능도 없지만 타입 명시는 프로그래밍 언어를 활용해 본 사람이라면 생각보다 필요한 부분이라는 것을 알 수 있을 것이다.
def add(a: int, b: int) -> int
return a + b
def ugly_function(vlaue: int, operation: Union[str, int, float, bool]) -> int:
...
int, bool, float 같은 기본적인 객체는 타입을 바로 명시해 주면된다. 리스트의 경우에는 어떻게 타입을 명히사는 게 좋을까? 만약 float객체를 갖고 있는 리스트가 있다면, typing 모듈을 사용하면 구체적으로 타입을 명시할 수 있다.
from typing import List
def total(xs: List[float]) -> float:
return sum(total)
종종 변수의 타입이 명확하지 않은 경우 힌트를 추가할 수 있다.
from typing import Optional
vlaues: List[int] = []
best_so_far: Optional[float] = None
'IT > Data Analysis' 카테고리의 다른 글
확률론과 통계학 (0) | 2024.08.15 |
---|---|
선형대수 (0) | 2024.08.12 |
데이터 시각화 (0) | 2024.08.11 |
파이썬 속성강좌_기초 (0) | 2024.08.11 |
데이터 과학 (0) | 2024.08.11 |