리스트는 순서가 있으며 중복을 허용하는 데이터들의 집합이다.
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = range(10)
print(a) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 출력
print(b) # range(0, 9)가 출력이 된다.
이처럼 list와 range는 내부적으로 다른 것이지만 비슷한 용도로 사용이 된다.
for i in a:
print(i, end=' - ') # end = 을 사용하면 개행 \n 대신 다른 문자 사용이 가능
print('//')
for i in b:
print(i, end=' - ')
print('//')
for loop를 돌아보면 결과는 같지만 range를 쓰는 편이 효율 적이다.
print(len(a)) # 10출력
print(len(b)) # 10출력
len으로 크기를 구하면 결과는 동일하다
print(list(b)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 출력
range를 list 형태로 꼭 나타내야 한다면 list 생성자를 이용한다.
파이썬은 c++과는 달리 문자열의 일부를 잘라내서 사용할 수 있다.
words = [
"flagrant",
"lawmaker",
"allow",
"alumina",
"concern",
"kiosk",
"incursion",
"offhand",
"especially",
"wanton",
"delectation",
"hebraic",
"inbred",
"agitate", # 마지막 원소에 , 를 써도 된다 (trailing comma)
]
print('-- index 3 번째에 있는 것 --')
print(words[3])
print('-- index 3 번째 이후에 있는 것 --')
print(words[3:])
print('-- index 3 번째 직전까지 있는 것 --')
print(words[:3])
print('-- index 3 번째 이후, 4번째 직전까지 있는 것 --')
print(words[3:4])
word = "especially"
print(word[3:8], word[2:])
# slicing 은 문자열에 대해서도 적용된다
python 에서 범위를 지정할 때는 대부분 [inclusive, exclusive) 형태를 사용한다.
(거의)유일하게 random.randinit(10, 15) 의 경우만 [inclusive, inclusive] 형태이다.
random.randrange(10, 15) 를 쓰면 [10, 15) 가 되기도 한다.
Dictionary는 검색을 위한 키 값을 갖는 데이터들의 집합이다. key, value의 쌍으로 이뤄진다.
Dictionary는 빨리 찾는 것이 가장 중요한 구조이기 때문에 Key들이 정렬되어 있지 않다
파이썬 3.6 이후부터는 정렬이 가능하긴 하다.
twice = { 'momo' : 80, 'sana' : 90.5 } # 중괄호와 :을 사용하여 정의
print(twice['momo']) # key가 momo인 항목의 value 80을 출력한다.
keys = [ 'momo', 'dahyun', 'jihyo' ]
for key in keys:
print('--key:', key)
if key in twice:
value = twice[key]
else:
value = '없다'
print('--- Value:', value)
세 개의 키 값에 대해서도 알아볼 수 있다.
words = [
"flagrant",
"lawmaker",
"allow",
"alumina",
"foxglove",
"fiche",
"concern",
"kiosk",
"clean",
"especially",
"wanton",
"addle",
"agitate",
"whinchat",
]
print('-- 각 글자별로 시작하는 단어가 몇개 있는제 세는 프로그램 --')
counts = dict() # Dictionary를 초기화
for word in words:
first_ch = word[0]
if not first_ch in counts: # Dictionary에 해당 key가 없으면
counts[first_ch] = 0
counts[first_ch] += 1
c++ 에서 사용하는 3항 연산자 a ? b : c를 파이썬에서는 b if a else c형태로 사용한다
ex) print("짝수" if num % 2 == 0 else "홀수")
from collections import defaultdict
counts2 = defaultdict(int)
for word in words:
first_ch = word[0]
counts2[first_ch] += 1
이렇게 되면 존재하지 않는 key값이 들어올 경우 int() 즉 0 값이 들어 있었던 것으로 간주한다
매번 key가 있는지 찾아보는 것이 귀찮을 경우 defaultdict를 사용한다
default(???)로 생성된 것은 key가 존재하지 않는다면 ???()로 만든다
Tuple은 순서가 있으며 중복을 허용하는 데이터들의 집합이다. 단, 데이터를 변경하는 것은 불가
t1 = 1, 2, 'hello', 3.5
t2 = (10, 10)
,로 연결하면 tuple이 되며 괄호를 안써도 되지만 보통 () 괄호를 사용한다
num,index,name,score = t1
arr = [100, 200]
first, last = arr
이처럼 tuple형태를 대입의 좌변에 사용할 수 있다
그리고 대입에서 배열을 우변, tuple을 좌변으로 놓을 수 있다.
xy1 = 123, 456 # xy1[1] += 10 같은 연산은 할 수 없다.
tuple은 읽기 전용 readonly이기 때문에 다음과 같은 연산이 불가능하다
def func():
print('This is a funcion')
func() # 'This is a funcion' 출력
함수를 사용하는 이유
인수 분해 : 함수를 두번 출력하고 싶으면 두번 호출하면 되고 인자를 넘어오는 부분만 다름
비슷한 것을 여러번 할거라면 공통적인 것을 함수로 정의하고 달라지는 것을 함수의 인자로 전달
동작의 추상화 : 프로그램을 짤 때, 함수 이름을 잘 짜놓으면 보는 사람이 편하다.
def func(arg):
print(' = funcion with (', arg, ')')
func('hello')
func('world')
이와 같이 달라지는 것만 넘겨준다.
value = 123
def some():
value = 456
print('in some(), value = ', value)
def other():
print('in other(), value = ', value)
some() # 456 출력 후 내부 value는 소멸
other() # 123 출력
다음과 같이 내부에서 선언한 변수는 함수 종료시 지역변수기 때문에 사라지지만 global변수인 외부 변수를 읽기만 하면 외부의 변수를 참조한다
def func():
print(value)
value = 10
func()
위와 같이 읽기만 한 함수를 쓰게 되면 오류가 생긴다.
def func():
global value
print(value)
value += 20
print(value)
func()
다음과 같이 global을 변수 앞에 선언하면 외부정의 변수를 읽고 쓸 수 있다.
def func(x, y):
print('point = ', x, y)
func(10, 20) # 직접 여러 개로 전달
arg_tuple = 12, 23
func(*arg_tuple) # *을 붙인 이유
arg_list = [34, 45]
func(*arg_list)
함수는 평범히 여러 개로 매개 변수 전달이 가능하고 포인터를 붙인 이유는 만약 포인터를 안 붙이고 arg_tuple만 넘겨주게 되면 첫번째 인자로 tuple을 넘긴 것이 된다.
def func(name, age, score = 0, method = None, msg = ' '):
if method == None:
method = 'the-default-method'
print('name=', name, 'age=', age, 'I got:', score, method, f"[{msg}]")
func('hello', 20)
func('hello', 20, 4.5, 'get')
func('hello', 20, 'get')
func('hello', 20, method = 'get')
arg_dict = { 'name': 'KKY', 'score': 123, 'msg': 'Hello,world', 'age':30 }
func(**arg_dict) # dict 형태로 함수 인자로 전달 가능
다음과 같이 다양한 매개변수로 넘겨줘도 알아서 찰떡같이 알아 듣고 넣어준다.
별 두개는 dict을 넘겨줄 때 사용된다.
def func_list(*args):
print('I got', len(args), 'arguments. first is', args[0])
func_list(10)
func_list(10, 20)
func_list(10, 20, 30)
func_list(10, 20, 30, 40)
def func_dict(**hash):
print('Got the dictionary argument:', hash)
func_dict(name='john', age=20, score=4.5, msg='Hello,world')
다음과 같이 받는 쪽에서 list나 dict으로 받을 수 있다.
def func_two_return(a, b):
sum = a + b
mul = a * b
return sum, mul
sum, mul = func_two_return(12, 5)
다음과 같이 리턴 타입을 두개이상의 값을 가진 투플로 리턴하는 것이 가능하다
class Hello:
pass
h = Hello()
파이썬에서는 줄을 비워 두면 안될 때 pass를 써야 한다.
그리고 함수 호출과 동일하게 타입 이름에 괄호를 열고 닫으면 해당 타입의 객체를 생성한다.
def func():
return 'This is a string'
flags = [True, False, True]
for flag in flags:
todo = Hello if flag else func
obj = todo()
print('flag 값은 :', flag, '이번에 얻은 것은 :', obj)
다음과 같이 함수 호출과 객체 생성이 동일한 문법 구조에 일어난다.
h1 = Hello()
h2 = Hello()
h1.name = 'David'
h2.age = 20
for obj in h1, h2
for attr in 'name', 'age':
if hasattr(obj, attr):
print(f'객체{obj}는 속성{attr}을 가지고 있어요')
이 문장에서 for문을 해석해보면 우선 obj에 h1을 대입하고 이중 for문으로 name과 age를 attr에 차례로 대입하여 obj안에 attr이 있는지를 검사한다.
이처럼 파이썬은 class 객체에 임의의 속성을 런타임에 추가할 수 있다.
class World:
def __init__(self): # c++의 this 대신 self를 사용한다. 멤버 함수는 첫번째 인자 self
self.name = 'Unknown'
self. age =
w1 = World()
w2 = World()
w2.name = 'David'
클래스를 생성할 때 같이 넣어주면 생성될 때부터 속성을 가지고 있는다.
class HelloWorld:
def __init__(self, name = 'UnKnown', age = 0): # 바로 초기화를 해줌(생성자 느낌)
self.name = name
self.age = age
def print(self):
print(f'name = {self.name}, age = {self.age}')
hw1 = HelloWorld('David', 20)
hw2 = HelloWorld('John', 23)
hw1.print()
hw2.print()
다음과 같이 생성자로 기본값을 설정하고 클래스 내에 함수를 정의할 수 있다.
class Worker:
def __init__(self, name):
self.name = name
def introduce(self):
print(f'name = {self.name}')
class Barista(Worker):
def __init__(self, name):
super().__init__(name)
def work(self):
print("열심히 커피 만들어요")
class Casher(Worker):
def __init__(self, name):
super().__init__(name)
def work(self):
print("주문 받고 돈받아요")
class Cleaner(Worker):
def __init__(self, name, place):
super().__init__(name)
self.place = place
def introduce(self):
print(f'내이름은 {self.name}. {self.place} 를 청소하지.')
def work(self):
print("구석구석 깨끗이 청소해요")
workers = [
Barista('David'),
Cleaner('Dijkstra', 'Seungho'),
Casher('John'),
Cleaner('Bob', 'tables'),
]
for worker in workers:
worker.introduce()
worker.work()
다음처럼 파이썬은 상속 관계를 만들 수 있고 각자 다른 코드가 실행된다.
파이썬도 format을 통해 스타일에 맞춰 출력을 할 수 있다.
students = [
( 'David', 22, (4.3 + 4.0 + 3.3) / 3 ),
( 'John Abdul', 25, (2.3 + 2.3 + 3.3) / 3 ),
( 'Chuck Norris', 124, (1.3 + 1.0 + 3.0) / 3 ),
( 'Karl Marx', 21, (3.3 + 2.0 + 4.3) / 3 ),
]
for st in students:
name, age, score = st
print(f'{name:^15} : {age:4} : {score:05.2f}')
'>'는 오른쪽 정렬 '<' 는 왼쪽 정렬, '^' 는 가운데 정렬이다
david = {'name':'David', 'age':22, 'score':3.866666}
print('%(name)-15s : %(age)4s : %(score)05.2f' % david)
이런 방식으로도 포맷팅이 가능하다
파이썬에는 매우 많은 내장 모듈이 존재한다.
import math
pt1, pt2 = [-150, -100], [150, 300]
distance = math.sqrt((pt1[0] - pt2[0])**2 + (pt1[1] - pt2[1])**2)
다음과 같이 math 모듈을 활용하여 sqrt를 사용할 수 있다.
angle_radian = math.atan2((pt1[1] - pt2[1]), (pt1[0] - pt2[0]))
angle_degree = 180 * angle_radian / math.pi
다음과 같이 역탄젠트로 두 점의 각도를 구할 수 있는데 atan2는 부호까지 신경써주기 때문에 atan2를 쓰면 된다.
대부분의 프로그램은 라디안 단위를 사용하기 때문에 degree로 변환해줄 필요가 있다.
dx = distance * math.cos(2 * angle_radian)
dy = distance * math.sin(2 * angle_radian)
두 점 사이의 거리를 알 때 각도만큼 회전한 좌표를 알기 위해서는 다음과 같은 cos, sin을 사용
dx = 회전의 중심 좌표 x + 반지름 r * sin(회전 각도θ / 360 * 2 * pi)
dy = 회전의 중심 좌표 y + 반지름 r * cos(회전 각도θ / 360 * 2 * pi)
다음의 식을 통해 회전 각도θ를 증가시켜 물체를 회전시킬 수 있다.
import pygame as pg
RED, GREEN, BLUE = (255, 0, 0), (0, 255, 0), (0, 0, 255)
BLACK, WHITE = (0, 0, 0), (255, 255, 255)
pg.init()
screen = pg.display.set_mode([900, 900])
font = pg.font.SysFont("arial", 16)
pg.display.set_caption('Test')
screen.fill(WHITE)