본문 바로가기

내일배움캠프 노드 4기/Today I Learned

22년 11월 21일 TIL (python 문법 정리)

JIT컴파일러 : 프로그램이 실행될 때 기계어로 컴파일 하는 방식

더보기

사용하게 될 경우 CPU에 직접 관여하는 네이티브 코드(=기계어)를 작성하여 프로그램을 구동시키며 프로그램의 동적(dynamic)인 실행환경(runtime)에 작동하기 때문에 한번에 모든 내용을 컴파일하는 일반적인 컴파일러보다 빈번하게 컴파일이 발생합니다. 만약 이미 컴파일된 내용이라면 JIT이 다시 컴파일하지 않고 해당 컴파일된 코드를 사용합니다.

 

JIT은 실행할 때 컴파일을 한다는 점이 중요합니다. 기존의 컴파일된 프로그램은 실행하려는 플랫폼(대표적으로 운영체제)에게 강한 종속을 받습니다. 만약 윈도우에서 컴파일을 했다면 이 프로그램을 단순히 Ctrl-C, Ctrl-V하는 식으로는 리눅스에서 쓸 수 없습니다. 프로그램이 리눅스에 필요하다면 리눅스에서 컴파일을 해야 합니다. (하지만 대부분의 경우 코드를 다시 짜는 일이 발생하는데, 이는 시스템 콜이 다르기 때문입니다. 간단한 콘솔 프로그램이라면 큰 변화가 필요없지만, UI가 들어가고 시스템에 관련되는 활동이 생기는 경우에는 프로그램이 절대 호환되지 않습니다.)

 

JIT은 기존의 컴파일 방식의 문제점을 중간에서 플랫폼에 맞게 변경해주는 방식으로 해결했습니다. 컴파일이라는 이름답게 속도 역시 기존 방식으로 컴파일된 프로그램들과 크게 차이나지 않습니다. JIT을 인터프리터 언어에 적용할 경우, 인터프리터 언어가 가진 유연한 플랫폼 특성과 컴파일 방식 특유의 빠른 속도를 모두 가질 수 있습니다.

 

하지만 JIT이 만능은 아닙니다. JIT을 사용하게 될 경우 컴파일을 실행시간에 하기 때문에 프로그램과 컴파일이 동시에 이뤄집니다. 다르게 생각해보면 컴파일할 때 필요한 자원을 실행시간에 공유하게 된다는 의미인데, 심각하리만큼 큰 단점은 아니지만 프로그램의 작업 환경에 따라 중요한 문제로 다가올 수 있습니다.

 

출처 : https://ammff.tistory.com/79


변수 선언과 자료형

a = 3        # 3을 a에 넣는다.
print(a)
b = a        # a에 들어 있는 값인 3을 b에 넣는다.
print(b)
a = 5        # a에 5라는 새로운 값을 넣는다.
print(a, b)  # 5 3

숫자형 자료형

다양한 형태의 숫자를 쓸 수 있습니다.
a = 5
b = 4.8

숫자 간에는 사칙연산이 가능합니다. 몫과 나머지도 구할 수 있어요.
a = 7
b = 2

a+b   # 9 
a-b   # 5
a*b   # 14
a/b   # 3.5

a+3*b         # 13 (여러 연산을 한 줄에 할 경우 사칙연산의 순서대로!)
(a+3)*b       # 20 (소괄호를 이용해서 먼저 계산할 부분을 표시해줄 수 있어요!)

변수에 저장된 값에 연산을 한 후 다시 그 값을 같은 변수에 저장할 수 있습니다. 
a = 5
a = a + 3 # 5에 3을 더한 값을 다시 a에 저장
print(a)  # 8

a += 3    # 줄여 쓸 수도 있다. 같은 의미!

a//b  # 3 (몫)
a%b   # 1 (나머지)
a**b  # 49 (거듭제곱)

불 자료형

특별한 자료형으로 참/거짓을 나타내는 불(Boolean) 자료형이 있습니다. 
x = True   # 참
y = False  # 거짓

# 소문자로 쓰면 자료형으로 인식하지 않고 변수명이라 생각해 에러가 납니다~
z = true   # name 'true' is not defined

True = 1   # True/False는 변수명으로 쓸 수 없어요!

보통 아래처럼 '비교연산자'의 결과로 나타내기 위해 쓰여요.
4 > 2      # True  크다
5 < 1      # False 작다
6 >= 5     # True  크거나 같다
4 <= 4     # True  작거나 같다
3 == 5     # False 같다
4 != 7     # True  같지 않다

불 자료형에는 논리연산자를 이용할 수 있습니다.
a = 4 > 2  # True
not a      # False    NOT 연산자로 참을 거짓으로, 거짓을 참으로 바꿔준다.

a and b    # False    AND 연산자로 모두 참이어야 참을 반환한다.
a or b     # True     OR 연산자로 둘 중 하나만 참이면 참이다.

문자열

# 작은 따옴표 또는 큰 따옴표. 둘 다 같아요!
a = "aa"
b = 'aa'

따옴표로 감싸지 않으면 변수이름을 뜻하기 때문에 꼭 구분해서 써야합니다!
a = 1
b = "a"
c = a
print(a, b, c) # 1 "a" 1

문자열 연산

문자열 간의 더하기는 두 문자열을 이어붙인 문자열을 반환합니다. 
first_name = "Harry"
last_name = "Potter"

first_name + last_name  # HarryPotter
first_name + " " + last_name  # Harry Potter

a = "3"
b = "5"
a + b    # 35

문자열과 정수를 더하면 에러!
a = "3"
a + 5    # 문자열과 숫자형은 더할 수 없어서 에러!

문자열의 길이는 len() 함수를 써서 구할 수 있습니다!
print(len("abcde"))           # 5
print(len("Hello, Sparta!"))  # 14
print(len("안녕하세요."))      # 6

문자열 메소드

이렇게 특정 자료형 뒤에 .을 붙이고 쓰는 내장 함수들을 '메소드(method)'라고 합니다

# 이메일 주소에서 도메인 'gmail'만 추출하기
myemail = 'test@gmail.com'

result = myemail.split('@') # ['test','gmail.com'] (뒤에 배울 '리스트'라는 자료형이에요 :))

result[0] # test (리스트의 첫번째 요소)
result[1] # gmail.com (리스트의 두 번째 요소

result2 = result[1].split('.') # ['gmail','com']

result2[0] # gmail -> 우리가 알고 싶었던 것
result2[1] # com

# 한 줄로 한 번에!
myemail.split('@')[1].split('.')[0]

특정 문자를 다른 문자로 바꾸기
txt = '서울시-마포구-망원동'
print(txt.replace('-', '>')) # '서울시>마포구>망원동'

인덱싱과 슬라이싱

문자열은 '문자들의 모임'이기 때문에 그 일부를 따로 떼어 부르는 방법이 있습니다. 
한 글자 씩 부를 때는 몇 번째인지 '인덱스'를 넣어 불러서 인덱싱이라고 합니다.
f="abcdefghijklmnopqrstuvwxyz"
f[1]   # b 파이썬은 숫자를 0부터 셉니다

문자열의 일부를 잘라낼 때는 슬라이싱이라고 해요.
f[4:15]  # efghijklmno           f[4]부터 f[15] 전까지, 총 15-4=11개!

f[8:]    # ijklmnopqrstuvwxyz    f[8]부터 끝까지, 앞의 8개 빼고!
f[:7]    # abcdefg               시작부터 f[7] 전까지, 앞의 7개!

f[:]     # abcdefghijklmnopqrstuvwxyz  처음부터 끝까지

특정 문자열로 자르고 싶을 때! split('문자열')을 활용합니다.
myemail = 'abc@sparta.co'

domain = myemail.split('@')[1].split('.')[0]
print(domain)

리스트

리스트 : 순서가 있는, 다른 자료형들의 모임
a = [1, 5, 2]
b = [3, "a", 6, 1]
c = []
d = list()
e = [1, 2, 4, [2, 3, 4]]

리스트의 길이도 len()함수를 사용해서 잴 수 있어요.
a = [1, 5, 2]
print(len(a))   # 3

b = [1, 3, [2, 0], 1]
print(len(b))   # 4

순서가 있기 때문에, 문자열에서처럼 인덱싱과 슬라이싱을 사용할 수 있습니다!
a = [1, 3, 2, 4]
print(a[3])  # 4
print(a[1:3]) # [3, 2]
print(a[-1]) # 4 (맨 마지막 것)

리스트의 요소로 리스트를 넣을 수 있다.
a = [1, 2, [2, 3], 0]
print(a[2])      # [2, 3]
print(a[2][0])   # 2
덧붙이기
a = [1, 2, 3]
a.append(5)
print(a)     # [1, 2, 3, 5]

a.append([1, 2])
print(a)     # [1, 2, 3, 5, [1, 2]]


# 더하기 연산과 비교!
a += [2, 7]
print(a)     # [1, 2, 3, 5, [1, 2], 2, 7]

정렬하기
a = [2, 5, 3]
a.sort()
print(a)   # [2, 3, 5]
a.sort(reverse=True)
print(a)   # [5, 3, 2]

요소가 리스트 안에 있는지 알아보기
a = [2, 1, 4, "2", 6]
print(1 in a)      # True
print("1" in a)    # False
print(0 not in a)  # True

딕셔너리

키(key)와 밸류(value)의 쌍으로 이루어진 자료의 모임
person = {"name":"Bob", "age": 21}
print(person["name"])

딕셔너리 만들기
a = {"one":1, "two":2}

# 빈 딕셔너리 만들기
a = {}
a = dict()

딕셔너리의 요소에는 순서가 없기 때문에 인덱싱을 사용할 수 없어요.
person = {"name":"Bob", "age": 21}
print(person[0])   # 0이라는 key가 없으므로 KeyError 발생!

딕셔너리의 값을 업데이트하거나 새로운 쌍의 자료를 넣을 수 있습니다.
person = {"name":"Bob", "age": 21}

person["name"] = "Robert"
print(person)  # {'name': 'Robert', 'age': 21}

person["height"] = 174.8
print(person)  # {'name': 'Robert', 'age': 21, 'height': 174.8}

딕셔너리의 밸류로는 아무 자료형이나 쓸 수 있어요. 다른 딕셔너리를 넣을 수도 있죠!
person = {"name":"Alice", "age": 16, "scores": {"math": 81, "science": 92, "Korean": 84}}
print(person["scores"])             # {'math': 81, 'science': 92, 'Korean': 84}
print(person["scores"]["science"])  # 92
딕셔너리 안에 해당 키가 존재하는지 알고 싶을 때는 in을 사용합니다.
person = {"name":"Bob", "age": 21}

print("name" in person)       # True
print("email" in person)      # False
print("phone" not in person)  # True

리스트와 딕셔너리의 조합

people = [{'name': 'bob', 'age': 20}, {'name': 'carry', 'age': 38}]

# people[0]['name']의 값은? 'bob'
# people[1]['name']의 값은? 'carry'

person = {'name': 'john', 'age': 7}
people.append(person)

# people의 값은? [{'name':'bob','age':20}, {'name':'carry','age':38}, {'name':'john','age':7}]
# people[2]['name']의 값은? 'john'

조건문

조건을 만족했을 때 특정 코드를 실행하도록 하는 문법
money = 5000
if money > 3800:
    print("택시 타자!")

else 와 elif

조건을 만족하지 못할 때 다른 코드를 실행하도록 하는 문법
money = 2000
if money > 3800:
    print("택시 타자!")
else:
    print("걸어가자...")
    
   
age = 27
if age < 20:
    print("청소년입니다.")
elif age < 65:
    print("성인입니다.")
else:
    print("무료로 이용하세요!")

반복문

같은 작업을 여러번 반복하고 싶을 때 사용하는 문법
fruits = ['사과', '배', '감', '귤']

for fruit in fruits:
    print(fruit)
    
for문 - enumerate, break
앞에 5개만 출력해보고 싶다면?

for i, fruit in enumerate(fruits):
    print(i, fruit)
    if i == 4:
        break

함수

함수는 반복적으로 사용하는 코드들에 이름을 붙여놓은 것입니다.
def hello():
		print("안녕!")
    print("또 만나요!")

hello()
hello()

조건문에 넣을 값을 바꿔가면서 결과를 확인할 때 쓰면 편합니다.\
def bus_rate(age):
		if age > 65:
		    print("무료로 이용하세요")
		elif age > 20:
		    print("성인입니다.")
		else:
		    print("청소년입니다")

bus_rate(27)
bus_rate(10)
bus_rate(72)

단순한 출력 뿐만 아니라 결과 값을 돌려주도록 함수를 만들 수도 있어요!
def bus_fee(age):
		if age > 65:
		    return 0
		elif age > 20:
		    return 1200
		else:
		    return 0     


money = bus_fee(28)
print(money)

튜플

튜플은 리스트와 비슷하지만 불변인 자료형 입니다. 마찬가지로 순서가 존재하죠!
a = (1,2,3)

print(a[0])

예를 들어 아래와 같은 작업이 불가합니다!
a = (1,2,3)
a[0] = 99

딕셔너리 대신 리스트와 튜플로 딕셔너리 '비슷하게' 만들어 사용해야 할 때 많이 쓰입니다!
a_dict = [('bob','24'),('john','29'),('smith','30')]

집합

집합은 말 그대로 '집합'을 구현하는 방법! 좋은점: 중복이 제거됩니다.
a = [1,2,3,4,5,3,4,2,1,2,4,2,3,1,4,1,5,1]

a_set = set(a)

print(a_set)

교집합 / 합집합 / 차집합도 구할 수 있어요
a = ['사과','감','수박','참외','딸기']
b = ['사과','멜론','청포도','토마토','참외']

print(a & b)  # 교집합
print(a | b)  # 합집합
print(a - b)  # 차집합

f-string

변수로 더 직관적인 문자열 만들기
scores = [
    {'name':'영수','score':70},
    {'name':'영희','score':65},
    {'name':'기찬','score':75},
    {'name':'희수','score':23},
    {'name':'서경','score':99},
    {'name':'미주','score':100},
    {'name':'병태','score':32}    
]

이름과 점수를 모두 출력
for s in scores:
    name = s['name']
    score = str(s['score'])
    print(name,score)
 
for s in scores:
    name = s['name']
    score = str(s['score'])
    print(name+'는 '+score+'점 입니다')
 
f-stirng을 이용하면 훨씬 간단하게 가능하답니다.
for s in scores:
    name = s['name']
    score = str(s['score'])
    print(f'{name}은 {score}점입니다')

예외처리

try - except 문 : 에러가 있어도 건너뛰게 할 수 있는 방법

20세 보다 큰 사람만 출력한다고 해봅시다.
그런데 만약, bobby가 age를 갖고 있지 않다면? - 데이터 하나가 잘못 들어간거죠!
people = [
    {'name': 'bob', 'age': 20},
    {'name': 'carry', 'age': 38},
    {'name': 'john', 'age': 7},
    {'name': 'smith', 'age': 17},
    {'name': 'ben', 'age': 27},
    {'name': 'bobby'},
    {'name': 'red', 'age': 32},
    {'name': 'queen', 'age': 25}
]

for person in people:
    if person['age'] > 20:
        print (person['name'])
        
그 때 아래와 같이 try except 구문을 이용하면 에러를 넘길 수 있답니다.
for person in people:
    try:
        if person['age'] > 20:
            print (person['name'])
    except:
        name = person['name']
        print(f'{name} - 에러입니다')

파일 분리하기

# main_test.py
from main_func import *

say_hi()

# main_func.py
def say_hi():
	print('안녕!')

한줄의 마법

if문 - 삼항연산자
 
만약 조건에 따라 다른 값을 변수에 저장하고 싶다면?
num = 3

if num%2 == 0:
    result = "짝수"
else:
    result = "홀수"

print(f"{num}은 {result}입니다.")

이것을 한 줄에 적는 것이 파이썬의 유일한 삼항연산자인 조건식입니다.
num = 3

result = "짝수" if num%2 == 0 else "홀수"

print(f"{num}은 {result}입니다.")


for문 - 한방에 써버리기
a_list의 각 요소에 2를 곱한 새로운 리스트를 만들고 싶다면?
a_list  = [1, 3, 2, 5, 1, 2]

b_list = []
for a in a_list:
    b_list.append(a*2)

print(b_list)

이것을 한 번에 쓸 수 있는 방법이 있죠!
a_list  = [1, 3, 2, 5, 1, 2]

b_list = [a*2 for a in a_list]

print(b_list)

map, filter, lambda 식

map - 리스트의 모든 원소를 조작하기
1차
def check_adult(person):
    if person['age'] > 20:
        return '성인'
    else:
        return '청소년'

result = map(check_adult, people)
print(list(result))

2차
def check_adult(person):
    return '성인' if person['age'] > 20 else '청소년'

result = map(check_adult, people)
print(list(result))

3차
result = map(lambda x: ('성인' if x['age'] > 20 else '청소년'), people)
print(list(result))


filter - 리스트의 모든 원소 중 특별한 것만 뽑기
map과 아주 유사한데, True인 것들만 뽑기! (map보다 훨씬 쉬워요!)

result = filter(lambda x: x['age'] > 20, people)
print(list(result))

함수의 매개변수

함수에 인수를 넣을 때, 어떤 매개변수에 어떤 값을 넣을지 정해줄 수 있어요. 순서 상관 없음!

def cal(a, b):
    return a + 2 * b

print(cal(3, 5))
print(cal(5, 3))
print(cal(a=3, b=5))
print(cal(b=5, a=3))

특정 매개변수에 디폴트 값을 지정해줄 수 있어요.

def cal2(a, b=3):
    return a + 2 * b

print(cal2(4))
print(cal2(4, 2))
print(cal2(a=6))
print(cal2(a=1, b=7))

입력값의 개수를 지정하지 않고 모두 받는 방법!

def call_names(*args):
    for name in args:
        print(f'{name}야 밥먹어라~')

call_names('철수','영수','희재')

이렇게 여러 개의 인수를 하나의 매개변수로 받을 때 관례적으로 args라는 이름을 사용합니다. 
arguments라는 뜻이에요!

키워드 인수를 여러 개 받는 방법!

def get_kwargs(**kwargs):
    print(kwargs)

get_kwargs(name='bob')
get_kwargs(name='john', age='27')

클래스

우선, 클래스를 언제 사용하는지 생각해보시죠!

예를 들어, 아주 많은 몬스터들의 HP를 관리해야 하면 어떻게 해야 편할까요?

방법1. → 리스트의 순서를 잘 지켜서 각 몬스터들의 hp를 잘 적어둔다.

방법2. → 몬스터마다 각자의 hp를 가질 수 있게 한다.

class Monster():
    hp = 100
    alive = True

    def damage(self, attack):
        self.hp = self.hp - attack
        if self.hp < 0:
            self.alive = False

    def status_check(self):
        if self.alive:
            print('살아있다')
        else:
            print('죽었다')

m = Monster()
m.damage(120)

m2 = Monster()
m2.damage(90)

m.status_check()
m2.status_check()

'내일배움캠프 노드 4기 > Today I Learned' 카테고리의 다른 글

22년 11월 23일 TIL  (0) 2022.11.23
22년 11월 22일 TIL 알고리즘  (0) 2022.11.22
22년 11월 18일 TIL  (0) 2022.11.18
22년 11월 17일 TIL  (0) 2022.11.17
22년 11월 16일 TIL  (0) 2022.11.16