본문 바로가기

파이썬 기초편(1) 본문

Programming/python

파이썬 기초편(1)

ksoes 2022. 5. 19. 22:14

 

 

● 출력

print('3 + 5 =', 8)
print(f'3 + 5 = {8}, {"name":5} {"jack"}')  # 3 + 5 = 8 name       jack
print('This {food} is {adjective}.'.format(food='spam', adjective='absolutely horrible'))

 

변수와 대입연산자

val = 30
x, y = 121, 797
y, x = x, y
print(x, y)  # 797, 121

30이 메모리공간에 저장이 되고 =에 의해 그 공간에 val이라는 이름이 붙게 된다. 여기서 val과 같이 메모리공간에 붙여진 이름을 가리켜 변수(valiable)라고 한다. 두번째 줄은 x와 y 변수에 각각 121과 797값을 저장한다. 세번째 줄의 코드로 인해서 파이썬에서는 두 변수에 저장된 값을 서로 바꾸는 것을 간단하게 할 수 있다.

 

이름의 이동

i = 2
print(id(i))  # 2065037000976
i = 45
print(id(i))  # 2065037002352
i = "str"
print(id(i))  # 2065037643184

id()는 객체의 고유 값을 리턴하는 함수로, 같은 변수명인 i지만, 각각 값을 넣었을 때 id값이 바뀌게 된다. 쉽게 생각해보자면 각 처음에는 2를 가리켰던 i가 45를 가리키고 그 다음엔 "str"을 가리키게 된다. 

 

 함수

def greet():  # 함수의 선언
    print("반갑습니다")
    print("파이썬의 세계로 오신 것을 환영합니다")
    
greet()  # 함수의 호출
def greet(name):  # name : 매개변수
    print("반갑습니다", name)
    print(name, "님은 파이썬의 세계로 오셨습니다)

greet("everyone")
def adder(num1, num2):
    ar = num1+num2
    return ar  # 함수실행 결과로 ar값을 반환

print(adder(1, 2))  # 3, type:int

여기서 우리가 사용하는 print("돈까스")도 print라는 이름의 함수를 호출하는 것이다. 문자열 "돈까스"를 전달하면서 print함수를 호출하는 것이다. 이것은 파이썬에서 미리 만들어서 제공하는 함수이고, 파이썬에는 이렇게 미리 만들어서 제공하는 함수들이 매우 많다.

파이썬 내장함수 : https://docs.python.org/ko/3/library/functions.html

 

이름짓기 규칙

· 파이썬은 대소문자를 구분한다.

· 숫자로 시작하면 안 된다.

· 키워드는 이름으로 쓸 수 없다.

· 변수와 함수의 이름은 소문자로 시작한다.

· 둘 이상의 단어를 연결하는 경우, _(언더바)를 이용해서 연결한다. ex) my_name

· 클래스명&Exception명은 CapWord를 적용, 단어는 모두 대문자로 시작한다. 언더바 사용X ex) NaverStockPrice, DataSplit

· 상수는 모두 대문자로 사용한다. 언더바 사용O

 

main()가 있는 방식으로 작성

소스파일에 담긴 내용은 위에서부터 아래로 실행되고, 파이썬에는 메인함수나 메서드가 없는 대신 메인 모듈이 있다. 처음 실행하는 소스파일이 메인 모듈이다. 

# prog.py

if __name__ == '__main__':  # 메인 프로그램으로서 실행
    # 문장 ...
bash % python3 prog.py # 메인으로서 실행

import prog # 라이브러리 임포트되어 실행

두 경우 __name__은 모듈의 이름이다. 그러나 메인으로서 실행될 때만 __main__이 된다.

라이브러리 임포트로서 실행할 떄는 메인 프로그램으로서 실행하는 문장을 실행하고 싶지 않을 수도 있다. 그러므로 어떤 쓰임새인지 if로 검사하는 것이다.

if __name__ == '__main__':  # 임포트될 때는 실행하지 않는다
# 예시 calc.py
def add(a, b):
    return a+b

def mel(a, b):
	return a*b

if __name__ == '__main__':  # 프로그램의 시작점일 때만 아래 코드 실행
    print(add(10, 20))
    print(mul(10, 20))

IDLE에서 실행하거나 python calc.py와 같이 인터프리터로 실행하면 10과 20의 합과 곱이 출력이 된다 즉, 프로그램의 시작점일 때는 if __name__ == '__main__': 아래의 코드가 실행이 된다. 그러나 import carc 처럼 carc.py를 모듈로 사용할 경우에는 아무것도 출력되지 않는다. 스크립트 파일을 모듈로 사용할 때는 calc.add, calc.mul 처럼 함수만 사용하는 것이 목적으로, 10과20의 합과 곱이 출력되는 코드는 필요가 없다.

 

 입력

num = input("입력하기 :")

 

 반복문

# range(start, stop, step)
for i in [1, 3, 5]:
for i in range(1, 11):  # for의 변수 i에 1부터 11-1까지 넣어서 반복
for i in range(0, 20, 2):  # range의 세번째 인자는 숫자의 간격을 나타냄
for i in range(20, 0, -2):  # step은 음수로 지정할 수 있다. 반복하면서 -2씩 줄어듬

 

정수와 실수의 표현

두 실수 사이에 존재하는 실수의 수가 무한대라는 특성 때문에 파이썬은 실수를 정수만큼 잘 표현하지 못한다.

정수 2는 정확히 값이 저장되지만, 실수를 저장하면 (최대한 오차를 줄이려 노력한) 오차가 있는 값이 저장된다. 출력결과를 봐도 잘 출력이 되는 것처럼 보이겠지만 오차가 너무 작아서 눈에 보이지 않을 뿐이다.

합 된 값이 예상한 결과값과 다르다. num2에 저장된 값은 1.1에 가까운 값일 뿐이다.

▶ 파이썬이 '정수를 표현 및 저장하는 방법'과 '실수를 표현 및 저장하는 방법'은 다르다

▶ 파이썬은 정수를 아주 정확히 표현하고 저장할 수 있다

▶ 파이썬은 실수를 오차 없이 표현하고 저장하지 못한다. 실수에는 약간의 오차가 있다.

 

int형과 float형을 대상으로 하는 기본적인 산술 연산

파이썬에서는 type함수를 통해 데이터 타입을 알 수 있다. type(3) 일 경우에는 <class 'int'>가 나오고 type(3.1)일 경우에는 <class 'float'>이 나온다. 이는 전달된 값이 각 int형과 float형임을 말한다.

 

int형과 float형을 대상으로 할 수 있는 산술연산

+    (덧셈)

-     (뺄셈)

*     (곱셈)

**   (거듭제곱)

/     (실수형 나눗셈) ▶ 5 / 2 = 2.5

//    (정수형 나눗셈) ▶ 5 / 2 = 2

%   (나머지) ▶5 % 2 = 1

 

int와 float형으로 변환

num = float("3.14")
a = int(4.2)
type(num)  # <class 'float'>
type(a)    # <class 'int'>

 

복합 대입 연산자

num += 1  #  num = num+1 와 같다
num -= 4  #  num = num-4 와 같다
num *= 5  #  num = num*5 와 같다

 

참과 거짓을 의미하는 값(데이터)

type(True)	# <class 'bool'>
type(False)	# <class 'bool'>

 

소스파일에 main함수 만들기

# main.py
def main:	# main 함수 선언
    print("Simple Frame")

main()		# main 함수 호출

 

if문: 조건이 맞으면 실행해라

if ~ else문: 이쪽 길! 아니면 저쪽 길!

if ~ elif ~ else문: 여러 길 중에서 하나의 길만 선택!

# if_elif_else.py
def main():		# main함수 정의
    num = int(input())
    if num>0:
    	print("0보다 큰 값")	# if문 조건절이 True이면 실행
    elif num<0:
    	print("0보다 작은 값")	# elif문 조건절이 True면 실행
    else:
    	print("0과 같음")	# 위의 조건절이 모두 False일 경우 실행

main()		# main함수 호출

 

True 또는 False를 반환하는 연산자들

# 비교 연산자
a > z	# a가 z보다 크면 True, 아니면 False
a < z	# a가 z보다 작으면 True, 아니면 False
a >= z	# a가 z보다 크거나 같으면 True, 아니면 False
a <= z	# a가 z보다 작거나 같으면 True, 아니면 False
a == z	# a와 z가 같으면 True, 아니면 False
a != z	# a와 z가 같지 않으면 True, 아니면 False
# 논리 연산자
a and b	# a와 b가 모두 True여야 True, 아니면 False
a or b	# a 와 b 둘 중 하나라도 True면 True, 아니면 False
not a	# a가 True면 False, False면 True

(num%2)==0 and (num%3)==0
'''
1. num%2, num%3
2. ==0, ==0
3. and
'''

 

리스트와 문자열을 대상으로도 동작하는 >=, <=, ==, !=

a >= b	# a가 b보다 크거나 같은가
a <= b	# a가 b보다 작거나 같은가
a == b	# a와 b가 같은가 (같으면 True, 다르면 False)
a != b	# a와 b가 다른가 (다르면 True, 같으면 False)
'abc' == 'abc'		# True
'abc' != 'abc'		# False

[1, 2, 3] == [1, 2]	# False
[1, 2, 3] != [1, 2]	# True

"abcd" >= "abced"	# False
"abc" < "abcde"		# True
[1, 2] <= [1, 2, 3]	# True
[1, 2] > [2, 3, 4]	# False

※ 파이썬에서 문자열 비교연산은 ascii코드 값으로 비교한다. 16진수 사각형 조건표에서 위치가 좌측에서 우측으로 갈 수록, 위보다 아래로 갈 수록 큰 값이다. python에서 문자의 ascii값을 얻고 싶다면 ord(c)함수를 사용한다.

 

True 또는 False로 답하는 함수들

# 문자열 관련 함수들
s.isdigit()		# 문자열 s가 숫자로만 이뤄져 있으면 True, 아니면 False 반환
s.isalpha()		# 문자열 s가 알파벳으로만 이뤄져 있으면 True, 아니면 False 반환
s.startwith(prefix)	# 문자열 s가 prefix로 시작하면 True, 아니면 False
s.endswith(suffix)	# 문자열 s가 suffix로 끝나면 True, 아니면 False

# is_phone_num.py
def main():		# main함수 정의
    pnum = input("번호입력:")
    if pnum.isdigit() and pnum.startwith("010"): # pnum이 숫자로만 이루어져있는지, 010으로 시작하는지 확인
    	print("정상적인 입력") # ex) 01022224444
    else:
    	print("잘못입력") # ex) 010 2222 4444 or 010-2222-4444

main()		# main함수 호출

 

in, not in

s.find(sub)		# 앞에서부터 sub를 찾아서 ※인덱스 값※을 반환, 없으면 -1 반환
s.rfind(sub)		# 뒤에서부터 sub를 찾아서 ※인덱스 값※을 반환, 없으면 -1 반환
s.startwith(prefix)	# prefix로 시작하면 True 반환
s.endwith(suffix)	# suffix로 끝나면 True 반환
# 찾는 내용의 위치정보가 필요하면 find를 이용, 찾는 내용의 존재유무만 확인하고자 한다면 in 연산자를 사용
e in S	# S에 e가 있으면 True, 없으면 False 반환
e not in S	# S에 e가 없으면 True, 있으면 False 반환

3 in [1, 2, 3, 4]	# True
"gee" in "sosi-gee"	# True

 

수(number)를 True와 False로 인식하는 방식

0이 오는 경우	# False가 온 것으로 간주한다
1이 오는 경우	# True가 온 것으로 간주한다

if num != 0:	# 다음과 같은 조건식을
if num:		# 이렇게 줄여서 쓸 수 있다. 이는 위의 코드와 같은 내용의 코드이다.

 

"True 또는 False가 와야 하는 위치에 '문자열'이 오면 이는 어떻게 해석될까요?" 혹은

"True 또는 False가 와야 하는 위치에 '리스트'이 오면 이는 어떻게 해석될까요?" 혹은

"True 또는 False가 와야 하는 위치에 '정수'가 오면 이는 어떻게 해석될까요?"

# 이는 bool 함수에 값을 전달해 보면 된다
bool(5)		# True
bool("what")	# True
bool([1, 2, 3])	# True

bool()		# False
bool("")	# False
bool([])	# False

함수 호출을 통해서 빈 문자열은 False, 비어있지 않은 문자열은 True로 해석됨을 알 수 있다. 문자열과 유사하게

빈 리스트는 False, 비어있지 않은 리스트는 True로 해석됨을 알 수 있다.

 

for 루프에 대한 복습

# for_sum.py
def main():
    sum=0
    for i in [1,2,3,4,5,6,7,8,9,10]: # for i in range(1,11): 와 동일
    	sum+=i
    print(f'sum= {sum}', end=' ')

main()

for 루프와 while 루프는 상당히 유사하다. 그러나 for 루프는 반복 횟수가 정해지난 반면, while 루프는 <조건>이 True가 될 때까지 반복된다는 차이가 있다.

 

True가 될 때까지 반복하는 while 루프

while <조건>:
	<조건이 True인 경우 반복 실행할 문장들>

# while_basic.py
def main():
    cnt=0
    while cnt < 3:	# cnt의 값이 3보다 작으면 반복 -> 조건문이 False일 때 반복문 탈출!
    	print(cnt, end=' ')
        cnt+=1

main()

 

for 루프와 while 루프의 비교

# for문
for <변수> in <반복 범위>:
	<for에 속하는 문장들>

# while문
while <반복 조건>:
	<조건이 True인 경우 반복 실행할 문장들>

'반복의 횟수가 정해지지 않는 경우'에는 while 루프를 이용하는 것이 좋다. for문을 이용할 수도 있지만 while문을 이용하는 것이 자연스럽다

 

break

# while_break.py
def main():
    i=0
    while i<100:
    	print(i, end=' ')
        i+=1
        if i==20:
            break	# 이 문장이 속한 반복문을 벗어난다 (break 위에서 가장 가까운 반복문을 탈출)
        # if i==20: break    # 이렇게 한줄에 작성하기도 한다. 위와 같은 문장
main()

 

continue

for i in range(1, 11):
    if i%2==0:
        continue	# 조건식이 True이면 for문으로 되돌아간다
    print(i, end=' ')	# 위의 continue가 실행되면 이 문장을 건너뛴다

# 결과: 1 3 5 7 9

i=0
while i<10:
    i+=1
    if i%3==0: continue	# i가 3의 배수이면 다음문장 건너뛰고 while로 되돌아간다.
    print(i, end=' ')

# 결과: 1 2 4 5 7 8 10

 

이중 for 루프

for i in [1, 2]:
    for j in ['a', 'b', 'c']:
        print(j * i, end=' ')

# 결과: a b c aa bb cc


sr = ['father', 'mother', 'brother']
cnt=0
for s in sr:	# s에는 father, mother, brother가 한번씩 담긴다
    for c in s:	# c에는 각 단어마다 한 글자씩 담긴다 ex)s=father, c=f,a,t,h,e,r
        if c == 'r': 
            cnt+=1
print(cnt)	# 4

 

◆ ch10 함수에 대한 추가적인 설명들

함수 만들기 복습

''' 함수의 유형 '''
# 아무 값도 전달받지 않는 함수
def great():
	print("반갑습니다")
    print("파이썬이 재미있으시죠?")

great()


# 값을 전달받는 함수
# 값을 반환하는 함수 (return 명령을 갖는 함수)
def adder(n1, n2):	# 전달되는 값을 매개변수 n1, n2로 받음
	r = n1 + n2
    return r	# r에 저장된 값을 반환

adder(3, 4)

 

이름을 지정해서 값 전달하기

def who_are_you(name, age):		# name과 age를 가리켜 ※매개변수※ 라고한다
	print("이름", name)
    print("나이", age)

''' 이렇게 호출할 수 있다 '''
who_are_you("내이름", 35)
who_are_you(35, "내이름")	# 순서가 바뀌면 바뀌어서 전달되게 된다.
who_are_you(name="내이름", age=35)	# 매개변수의 이름을 알고있다면 이렇게 호출할 수 있다.
who_are_you(age=35, name="내이름")	# 매개변수의 이름을 지정해서 값을 전달하면 전달순서는 상관이 없어진다!
print(1,2,3, end='_ㅇㅁㅇ_')	# 출력의 끝에 '_ㅇㅁㅇ_'도 출력하라는 의미
				# 결과: 1 2 3_ㅇㅁㅇ_

''' 반면 print함수의 매개변수 sep에 전달된 내용은 출력 내용들 사이사이에 출력이 되어 
    출력내용을 구분하는 용도로 사용이 된다'''
print(1,2,3, sep=', ^')	# 결과: 1, ^2, ^3, end와 다르게 끝에는 sep이 출력이 되지 않는다!

''' 물론 매개변수 sep와 end에 값을 동시에 전달할 수 있다 '''
print(1,2,3, sep='***', end='///')	# 결과: 1***2***3///

 

디폴트(default) 값

# age의 디폴트 값은 0, 만약 age를 채울 값이 전달되지 않으면 0을 전달하겠다는 의미
def who_are_you(name, age=0):	# 전달된 값이 있으면 전달된 값이 담긴다.
    print(name)
    print(age)

만약 함수를 만들 때 디폴트 값을 갖는 매개변수와 갖지 않는 매개변수가 함께 존재한다면, 반드시 디폴트 값을 갖는 매개변수가 뒤로 와야한다. 예를 들어 매개변수가 총 4개이고 그 중 2개가 디폴트 값을 갖는다면, 다음과 같이 이 2개를 뒤에 뒤쪽에 두어야 한다.

def have_default_value(n1, n2, n3="df1", n4="df2"):
    print(n1, n2, n3, n4)

have_default_value(1, 2, 3, 4)

왜 그래야 하는지 보자. 만약 (1)과 같은 함수가 있을 때는 n1에만 값을 전달하고 n2에는 값을 전달하지 않을 수 있다. 그러나 (2)처럼 함수가 만들어졌을 때, k2에만 5를 전달하는 방법이 있나? func2(5)라고 호출하면 5는 첫번째 매개변수인 m1에 전달되고 m2에는 아무것도 전달되지 않는다. 즉 (2)의 경우 디폴트 값이 쓸모가 없다. 그래서 (2)와 같은 함수 정의를 허용하지 않는 것이다.

# (1)
def func1(n1, n2 = 7):
	pass	# pass라고 쓰면 아무 일도 하지 않는 함수가 된다
    
func1(5)


# (2)
def func2(m1 = 7, m2):	# 이렇게 선언할 경우 SyntaxError가 발생한다.
	pass

func2(5)	# m1에 5가 들어가고 m2에는 아무 값이 들어가지 않게 된다.

 

함수의 매개변수 참조 관계

def func(s):
    s[0] = 0	# 리스트의 첫번째 값을 0으로 수정
    s[-1] = 0	# 리스트의 마지막 값을 0으로 수정

st = [1, 2, 3]
func(st)
st		# 결과:[0, 2, 0], 함수 호출 후 st가 [1, 2, 3]에서 [0, 2, 0]으로 바뀌었다!

func함수를 호출해 매개변수로 받은 리스트 s의 값을 수정했더니 리스트 st의 값이 바뀌었다. 분명 func에서는 return문도 없고 함수가 끝난 후 함수의 매개변수는 끝나는 걸로 알고 있어 st가 [1, 2, 3]으로 나올 줄 알았다. 어떻게 된 것일까?

 

이 예제에서 이야기 하고 싶은 내용은 다음과 같다.

"st에 담겨있는 리스트 [1, 2, 3]이 매개변수 st에 어떻게 전달되는가?"

위에서 선언한 변수 st에는 리스트가 담겨있다.(st를 값에 붙는 이름표라고 생각하자) 그리고 함수 func를 호출하고 st가 가지고있는 [1, 2, 3]을 전달하였다. 그러면 변수 st와 매개변수 s의 관계는 어떻게 될까?

st의 값이 s에 복사가 되어 저장될까?

파이썬은 매개변수를 위해 별도의 메모리 공간을 할당하지 않는다. 대신에 같은 메모리공간에 하나의 이름을 더 붙이는 방식으로 '매개변수로 전달되는 값'을 처리한다.

같은 메모리공간을 가리키도록 이름을 하나 더 붙이는 방식으로 처리한다
st와 s의 객체 고유 값이 똑같다

id()는 객체를 입력 값으로 받아서 객체의 고유값(레퍼런스)을 반환하는 함수이다. id는 파이썬이 객체를 구별하기 위해서 부여하는 일련번호다. 숫자로서 의미는 없습니다. id는 동일한 객체인지 여부를 판단할 때 사용한다.

파이썬의 모든 객체는 (그 종류에 상관없이) 매개변수에 전달되면 위에 설명한 방식으로 처리가 된다. 그러니까 이름이 하나 더 붙는다.

 

Comments