요즘들어 파이썬 공부를 시작했다.
C와 C++를 주 언어로 사용하고 파이썬은 맛보기정도로만 알고있던 나..
아직 파이썬 기본단계이지만 벌써 외워야 할 것들이 있다..
파이썬의 기능과 함수가 너무 여러개라 정리하기 위해 작성한다.

문자열


파이썬에서는 문자열을 슬라이싱하는 방법이 따로 존재한다.
문자열 “안녕하세요”를 예시로 print("안녕하세요"[0:2])의 경우 “안녕” 이 출력된다.
역순으로 출력하는 방법도 있는데, print("안녕하세요"[-1])의 경우 “요” 가 출력된다.

C에서 strlen함수는 파이썬에서 len함수로 사용된다.
C에서 %d, %s 등 특정 변수값을 출력에 사용할 경우, 파이썬에선format함수를 사용한다.
예를 들어, 년, 월, 일을 출력하기 위해서 format함수를 사용하면 print("{}년 {}월 {}일".format(year, month, day)) 이런 식으로 사용한다.

리스트


리스트의 요소를 추가하는 함수로 extend라는 함수가 존재한다.
예를 들어 list.extend([4,5,6])의 코드를 수행하면 list 배열에 4, 5, 6의 원소들이 추가된다.

리스트의 요소를 제거하는 방법으로 del list[index]list.pop(index)가 존재한다.
둘 다 해당 index의 요소가 제거된다.
추가로 del 명령어의 인덱스는 범위를 지정해 여러개의 요소를 한번에 제거할 수 있으며 pop 함수는 매개변수에 아무것도 없으면 제일 뒤의 요소가 제거된다.

또 제거하는 다른 방법으로 remove함수가 존재하는데, list.remove(value)를 사용하면 list에 있는 value값이 지워지게 된다. 하지만 이는 제일 앞에 있는 값만을 제거하며, 같은 값이 여러개 존재하고 이를 다 지우고 싶은 경우 반복문을 통하여 모두 지워야 한다.
리스트의 모든 값을 제거할 때는 list.clear()를 사용하면 된다.

딕셔너리


파이썬은 리스트와 유사한 딕셔너리라는 것이 존재한다.
이는 키를 기반으로 값을 저장한다.
변수 = {키:값, 키:값, ... 키:값}의 형식으로 선언하며, 요소에 접근할 땐 키를 이용하여 값에 접근한다.
새로운 값을 추가하려면 딕셔너리[새로운 키] = 새로운 값으로 변수를 선언해주듯이 사용하면 새로운 값이 추가된다.
값을 삭제할 땐 del dict["name"]과 같은 식으로 해당 값의 키를 입력하면 삭제된다.
특정 키가 존재하는지 확인하기 위해 dict.get("key")를 사용하면 확인할 수 있다.
만약 키가 존재하지 않는다면 None을 출력한다.

반복문


range(A,B,C)는 A부터 B-1까지의 정수로 범위를 만드는데, C만큼의 차이를 갖는다.
수식에 나누기를 넣는 경우 // 의 정수 나누기 연산자를 주로 사용한다.
만약 / 의 나누기 연산자를 할 경우 float형태가 되기 때문에 오류가 발생한다.

반복문을 반대로 출력할 때엔 range(4,-1,-1)같은 식으로 출력하면 4부터 0까지 내려가게 된다.
또, list[::-1]과 같은 방법으로 반대로 출력할 수 있다.
이를 reversed함수를 사용하여 reversed(range(5))와 같은 식으로 사용하면 마찬가지로 4부터 0까지 내려가게 된다.
이 reversed함수의 결과는 제네레이터라는 것을 유의하여 함수의 결과를 여러번 사용하는 실수를 하지 않도록 하자.

enumerate()함수는 리스트를 (index,value)의 형태로 변환한다.
따라서 반복문에 for i value in enumerate(list) 와 같은 형식으로 변수를 두개 활용이 가능하다.
딕셔너리는 같은 동작을 하는 함수로 items()함수를 사용한다.

리스트 내포라는 것이 있다.
리스트를 초기화할때 list = [i\*i for i in range(0, 20, 2)]
이런 식으로 초기화하면 짝수의 제곱수로만 이루어진 리스트가 생성된다고 한다.
if문을 사용하여 list = [i\*i for i in range(0, 20, 2) if i != 2] 이런 식으로 2를 제외한 값들에 대해 적용할 수도 있다고 한다.

문자열을 선언할 때 string = ("A " "B " "C ")와 같은 식으로 선언해도 string은 “A B C”가 된다고 한다.
이를 활용하여 반복문 혹은 조건문 내에 출력을 할 때 개행때문에 코드가 번잡스러워지는 것을 방지할 수 있다.

string.join(list)함수는 리스트의 요소를 문자열로 연결한다.
따라서 "\n".join(list)를 하면 자연스럽게 리스트 내 문자열들 사이에 개행을 할 수 있겠다.

내가 공부하는 파이썬 책에서는 next()함수를 적용하여 하나하나 꺼낼 수 있는 요소를 이터레이터 라고 지칭한다.
reversed함수의 리턴값이 이터레이터라서 반복문의 매개변수로 전달할 수 있고, next함수로 하나 하나 꺼내주는 것이라고 하는데 아마 이 이터레이터라는 것이 주소값을 의미하는 단어인 것 같다.
(확실친 않아 후에 정확하게 알게 되면 수정하도록 하겠다.)

함수


파이썬에도 가변 매개변수가 존재한다.

def func(var1, var2, ..., *values):
	~~~	#body

위와 같은 방식으로 사용된다.

예시로 n개의 문자열을 사용하는 print_n_times라는 함수가 있다고 가정하면

print_n_times(3, "Hello", "Happy", "Python")

위와 같은 방식으로 사용할 수 있겠고, 3은 C에서 argc, 뒤의 문자열들은 argv에 들어갈 문자열들이라고 생각하면 C를 했던 개발자들에게 이해가 쉽게 될 듯 하다.

기본 매개변수는 가변 매개변수와 같이 사용할 수 없다.
여기서 기본 매개변수란 n=2와 같은 식으로 함수의 매개변수가 초기화되어있는 형태이다.
이때 사용하는 것이 키워드 매개변수라고 한다.

while True:
	print(".", end=" ")

위와 같은 코드에서 end=” “ 이부분이 키워드 매개변수이다.
즉 이름을 지정해서 해당 매개변수에 직접 입력하는 방법으로 사용할 수 있는 것이다.

재귀함수

재귀함수는 활용을 잘 하지 못하면 쓸데없는 연산을 하게되고 비효율적이게 된다는 문제가 있다.
이 문제를 해결하기 위해 memoization이라는 기술을 사용한다.
이는 한번 계산한 결과를 메모리에 메모하여 사용하는 기술이다.

global var

이 책은 이 부분에서 외부의 변수를 참조하기 위해 위의 키워드를 알려준다.

dict = {
	1: 1,
	2: 2
}
def fibo(n):
	if n in dict:
		return dict[n]
	output = fibo(n-1) + fibo(n-2)
	dict[n] = output
	return output

하지만 예시코드에서는 위 코드를 예시로 알려주는데, 굳이 global을 알려줘놓고 왜 여기선 global을 안썼는데 외부에 딕셔너리를 선언하고 함수 내부에서 이를 쓰는거지? 라고 초보자가 생각할 수 있겠다 싶었는데… 곰곰히 생각해보니 나도 잘 모른다.. 왜지..?

(수정)
아.. 내가 파이썬을 잘 몰라서 혼자 이상한 문제에 잠시 빠졌던 것 같다.
global 명령어는 전역변수의 값을 바꾸기 위해서 함수 내에서 사용하는 것이라고 한다.
그럼 전역 범위의 딕셔너리는 함수 내에서 함부로 값을 바꿔도 상관없는 건가? 이건 아직 답을 잘 모르겠다.
사실 딕셔너리는 파이썬에서 처음 본 기능이라.. 나중에 더 공부해봐야할 듯 싶다.

함수 고급

튜플이란 리스트와 비슷한 자료형이지만 한번 결정된 요소는 바꿀 수 없다.
람다란 함수를 간단하고 쉽게 선언하는 방법이라고 한다.

튜플

tuple_test = (10, 20, 30)

튜플의 선언은 위와 같이 한다.
이때 튜플과 리스트가 다른 점은 내부 요소가 변경이 되지 않는다는 것이다.
요소가 하나인 튜플은 (10, ) 이와 같이 선언한다.
튜플은 괄호를 생략해도 튜플로 인식할 수 잇는 경우엔 괄호를 생략해도 된다고 한다.

a, b = 10, 20
a, b = b, a

위와 같이 사용하면 a 값과 b 값이 바뀐다.

튜플은 함수의 리턴에 사용하는데, 이는 여러 개의 값을 리턴하고 할당할 수 있기 때문이다.

for i, value in enumerate([1, 2, 3, 4, 5, 6])

위 코드에서 i, value도 튜플이라고 한다.

람다

함수를 매개변수로 전달하는 코드를 조금 더 효율적으로 작성하기 위해 람다라는 기능을 제공한다고 한다.

함수의 매개변수로 함수 전달 예제

함수를 매개변수로 전달하는 대표적인 표준 함수는 map()함수와 filter()함수가 있다.

map(함수, 리스트)

map 함수는 위와 같이 사용한다.
리스트의 요소를 함수에 넣고 리턴된 값으로 새로운 리스트를 구성해준다.

filter(함수, 리스트)

filter 함수는 위와 같이 사용한다.
리턴된 값이 True인 것으로 새로운 리스트를 구성해준다.

def pow(item):
	return item*item
def under_3(item):
	return item < 3

list_a = [1, 2, 3, 4, 5]
print("map(pow, list_a):", list(map(pow, list_a)))
print("filter(pow, list_a):", list(filter(under_3, list_a)))

위는 map 함수와 filter 함수의 예제이다.

map(pow, list_a): [1, 4, 9, 16, 25]
filter(pow, list_a): [1, 2]

실행 결과는 위와 같다.

람다는 위처럼 함수 구문 작성도 번거롭고, 코드 공간 낭비가 있다는 생각으로 고안된 것이다.

lambda 매개변수: 리턴값

위와 같은 형태로 만든다.

pow = lambda x: x*x
under_3 = lambda x: x<3

이전 코드의 함수를 람다로 변환하면 위와 같이 변환되며 함수를 쉽게 작성할 수 있다.

list_a = [1, 2, 3, 4, 5]
print("map(pow, list_a):", list(map(lambda x: x*x, list_a)))
print("filter(pow, list_a):", list(filter(lambda x: x<3, list_a)))

위와 같은 방식으로 함수 자리에 람다를 바로 매개변수로 넣어 더 깔끔하게 코드를 작성할 수 있다.

lambda x, y: x * y

위 코드처럼 매개변수가 여러 개인 람다도 만들 수 있다.

파일처리

객체 = open(문자열: 파일 경로, 문자열: 읽기 모드)

파일을 열 때는 open()함수를 사용한다.
읽기 모드에는 w(write), a(append), r(read) 모드가 있다.

객체.close()

파일을 닫을 때에는 close()함수를 사용한다.

file = open("example.txt", "w")
file.write("Hello Python")
file.close()

위 코드는 파일 입출력 코드의 예제이다.

파일을 열고 닫지 않는 실수를 방지하기 위해 with 키워드라는 기능이 생겼다.

with open("example.txt", "w") as file:
	file.write("Hello Python")

위와 같은 방식으로 사용하면 with 구문이 종료될 때 자동으로 파일이 닫힌다.

파일을 읽을 땐 권한을 r로 사용하고, contents = file.read()와 같은 방식으로 읽어들이면 된다.

with open("info.txt", "r") as file:
	for line in file:
		(name, weight, height) = line.strip().split(", ")

위 코드는 이름, 몸무게, 키 로 구성되어 있는 info.txt파일을 읽는 코드이다.
strip()함수는 문자열의 맨앞과 맨뒤의 whitespace를 제거하는 함수이며 중간 중간의 구분자들은 split함수를 통해 각 단어를 쪼갠 것이다.

제너레이터

제너레이터는 이터레이터를 직접 만들 때 사용하는 코드이다. 함수 내부에 yield 키워드를 사용하면 해당 함수가 제너레이터 함수가 된다고 한다. 제너레이터 함수는 함수를 호출해도 함수 내부의 코드가 실행되지 않는다.

def test():
	print("A")
	yield 1
	print("B")
	yield 2
	print("C")

output = test()
a = next(output)	#A가 출력된다.
print(a)			#yield의 숫자가 출력된다.
b = next(output)
print(b)
c = next(output)

위 코드를 실행하면 함수 내부의 내용이 차근 차근 진행되는 모습을 확인할 수 있다.
next()함수 이후 yield함수를 만나지 못하면 에러 메세지를 출력하기에 위 코드는 에러 메세지가 출력된다.
이 예시처럼 제너레이터는 함수의 코드를 조금씩 실행할 때 사용한다. 이는 메모리의 효율성을 위한 것이라고 한다.

예외 처리


try-exception

try:
	예외가 발생할  있는 코드
except:
	예외가 발생했을  실행할 코드
else:
	예외가 발생하지 않았을  실행할 코드
finally:
	무조건 실행할 코드

요즘 프로그래밍 언어는 예외를 처리할 수 있는 구문이 제공된다.
try-except 구문이 예외를 처리할 수 있는 구문이며 사용법은 위 코드와 같다.
또, except구문에 아무것도 쓰지 않으면 오류가 발생하기 때문에 이때 pass를 활용한다고 한다.
else문은 보통 예외가 발생할 수 있는 코드만 try에 넣고 그 외에 코드 전부를 넣는다고 한다.

pass

list_a = ["52", "273", "spy", "103"]
list_num = []
for i in list_a:
	try:
		float(item)
		list_num.append(item)
	except:
		pass

pass를 활용하는 방법엔 위와 같은 방법이 있다.
이런 방식을 사용하면 list_a에 있는 숫자를 모두 list_num에 추가할 수 있다.

finally

try:
	file = open("ex.txt","w")
	예외발생()
	file.close()
except Exception as e:
	print(e)

finally:
	file.close()

finally문은 위와 같이 try문에서 중간에 예외가 발생해 파일이 닫히지 않았을 경우에 대비하여 활용될 수 있다.
위 예제에서 print(e)를 하면 예외 발생 메세지가 출력된다.

except

except ValueError:
	print("ValueError")
except IndexError:
	print("IndexError")
except Exception:
	print("Unexpected Error")

위 코드처럼 except문 옆에는 예외의 종류를 입력해서 예외를 구분할 수 있다.
특정 에러에 대한 except문만 사용하면 프로그램이 종료될 수 있으니 마지막에는 Exception을 넣어 프로그램이 종료되는 것을 방지하는 것이 좋다.

raise

프로그램을 개발할 때 확실하게 예외를 발생시키는 방법이 있다.

raise 예외 객체
# ex) raise NotImplementedError

위와 같은 방식으로 사용하면 된다.

모듈


표준 모듈 등의 정보가 궁금할 땐 가장 먼저 파이썬 공식 문서를 확인하도록 하자.

from 모듈 이름 import 가져오고 싶은 변수 또는 함수
# ex) from math import sin, cos, tan

모듈을 import할 때 변수나 함수 앞에 무언가를 계속 입력하는것이 귀찮다고 느껴질 땐 from구문을 사용한다.
모든 기능을 가져오는 것이 목적이라면 import 뒤에 *을 붙인다.

import 모듈 as 사용하고 싶은 식별자
# ex) import math as m

모듈의 이름을 바꾸어 사용하고 싶은 경우 위와 같이 as 구문을 사용한다.

random

함수 설명
random() 0.0<= x < 1.0 의 float 리턴
uniform(min,max) min과 max사이의 float 리턴
randrange() 지정한 범위의 int 리턴
choice(list) 리스트 내부 요소를 랜덤하게 선택
shuffle(list) 리스트 내부 요소를 랜덤하게 섞음
sample(list, k=<숫자>) 리스트 요소 중 k개 선택

os

함수 설명
getcwd() 현재 폴더
listdir() 현재 폴더 내부 요소
mkdir() 폴더 생성
rmdir() 폴더 삭제
rename(original, new) 폴더 이름 변경
remove() 폴더 삭제

datetime

함수 또는 변수 설명
datetime.now() 현재시각
year
month
day
hour
minute
second

데코레이터

파이썬에는 데코레이터라는 기능이 있다. 코드를 보면 @로 시작하는 구문을 데코레이터라고 부른다.
데코레이터는 만드는 방법에 따라 함수 데코레이터와 클래스 데코레이터로 나눌 수 있다.

def test(func):
	def wrapper():
		print("Hey")
		func()
		print("Hi")
	return wrapper
	
@test
def hello():
	print("hello")

hello()

위 코드는 함수 데코레이터의 예시이다. test()함수에서 wrapper()함수를 리턴하므로 최종적으로 hello에 함수가 들어가 hello() 형태로 호출할 수 있다.

책을 보고 나온 설명대로 써두긴 했는데, 아직 이해가 잘 되지 않았다.. 무슨말이지..
더 공부한 후에 제대로 알게되면 봤을 때 이해가 편하도록 글을 수정하겠다.

__name__

프로그래밍 언어에서 프로그램의 진입점을 엔트리 포인트 혹은 메인이라고 부른다.
이러한 엔트리 포인트 또는 메인 내부에서의 __name__은 “__main__“이다.
모듈의 내부에서 __name__은 모듈의 이름을 나타낸다.
이를 활용하면 현재 파일이 모듈로 실행되는지, 엔트리 포인트로 실행되는지 확인할 수 있다.

만약 외부에 모듈을 만들고 해당 모듈에서 출력을 하도록 코드를 짠 경우, 해당 모듈을 import한 파일을 실행하면 외부 모듈의 출력문이 출력되는 경우가 있다.

if __name__ == "__main__":
	write your code

그러한 경우 외부 모듈에 위와 같은 조건문을 작성하여 출력문을 안에 넣어 현재 파일이 엔트리 포인트인지 구별하는 방식으로 사용할 수 있다.

패키지

패키지란 모듈이 모여 구조를 이루는 것을 말한다.
패키지를 읽을 때 어떤 처리를 수행해야 하거나 패키지 내부 모듈들을 한번에 가져오고 싶을 때 __init__.py파일을 만들어 사용한다.
패키지를 읽어 들일 떄 __init__.py파일을 가장 먼저 실행한다.
따라서 패키지와 관련한 초기화 처리등을 할 수 있다. 해당 파일에선 __all__이라는 이름의 리스트를 만드는데, 이 리스트에 지정한 모듈들이 from package import *를 했을 때 전부 읽어 들여진다.

인터넷 이미지 저장

from urllib import request

target = request.urlopen("http://www.hanbit.co.kr/images/common/logo_hanbit.png")
output = target.read()
file = open("output.png","wb")
file.write(output)
file.close()

이미지는 바이너리 데이터이기 때문에 접근 권한에서 wb로 바이너리 데이터인 것을 명시해줘야 한다.

클래스


여러가지 속성을 가질 수 있는 대상을 객체 라고 한다.
객체와 관련된 코드를 분리할 수 있게 하는 것이 객체 지향 프로그래밍의 핵심이며, 개발자들은 이를 위해 클래스라는 구조를 만들게 되었다.

class 클래스 이름:
	클래스 내용

클래스는 위와 같은 구문으로 생성한다.
파이썬 개발자라면 클래스 이름을 캐멀 케이스로 짓는 것이 좋다고 한다. ex) CamelCase

만들어진 클래스는 클래스 이름과 같은 함수인 생성자를 사용하여 객체를 만든다.

인스턴스 이름(변수 이름) = 클래스 이름() #생성자 함수

이렇게 클래스 기반으로 만들어진 객체를 인스턴스라고 한다.

생성자

class 클래스이름:
	def __init__(self, 추가 매개변수):
		pass

클래스 내부 함수는 첫 번째 매개변수로 반드시 self를 입력해야 한다. (단순 식별자이므로 변수 이름으로 활용해도 상관은 없지만, 대부분의 개발자가 self를 사용하므로 기본 규칙을 지키는 게 좋다.)

class Student:
	def __init__(self,name,korean,...):
		self.name = name
		self.korean = korean
		...
students = [Student("이름",87,...), Student("이름", 92,...)]

이는 class 생성 예시이다.

소멸자

class 클래스이름:
	def __del__(self):
		pass

인스턴스가 소멸될 때 호출되는 함수는 소멸자라고 부른다.

메소드

클래스가 가지고 있는 함수를 메소드라고 한다.

class 클래스이름:
	def 메소드 이름(self, 매개변수):
		pass

이는 다른 언어와 똑같이 class 내부에 함수를 선언하면 된다.

클래스의 추가적인 구문

어떤 클래스를 기반으로 속성과 기능을 물려받아 새로운 클래스를 만드는 상속, 이러한 상속 관계에 따라 어떤 클래스를 기반으로 만들었는지 확인할 수 있는 isinstance()함수 등이 대표적인 부가기능이라고 한다. 이런 기능에 대해 알아보자.

isinstance(인스턴스, 클래스)

이 함수는 인스턴스가 해당 클래스 기반으로 만들어졌다면 True, 아닐 시 False를 리턴한다.

특수한 이름의 메소드

객체 뒤에 .을 입력하여 살펴보면 다양한 함수들이 존재한다.
이는 클래스를 사용할 때 제공해주는 보조기능이며 __<이름>__() 형태로 되어 있다. 이러한 메소드는 특수한 상황에 자동으로 호출되도록 만들어졌다.

def __str__(self,student):
	return "{}/t{}\t{}".format(self.name,self.get_sum(student),self.get_ave(student))

예시로 str()을 클래스 내부에 정의하면 str함수를 호출할 때 자동으로 호출된다.
위 코드를 한 후에 print(str(student))를 출력하면 위 format대로 출력된다.

클래스 변수와 메소드

class 클래스이름:
	클래스 변수 = 

위 방법을 통해 클래스 변수를 만들 수 있으며, 접근은 클래스이름.변수 이름을 통해 접근할 수 있다.

클래스 함수

클래스 함수는 생성하는 방법이 특이하다. 데코레이터를 통해 함수를 생성한다.

class 클래스 이름:
	@classmethod
	def 클래스 함수(cls, 매개변수):
		pass

클래스 함수의 첫 번째 매개변수엔 클래스 자체가 들어간다.

프라이빗 변수

class Circle:
	def __init__(self,radius):
		self.__radius = radius

클래스 내부의 변수를 외부에서 사용하는 것을 막고 싶을 때 인스턴스 변수 이름을 __<변수 이름=""> 형태로 선언하면 된다.

게터와 세터

클래스 외부에서 직접 __변수에 접근할 수 없기 때문에 간접적으로 접근할 수 있는 방법을 찾아야 한다.
이때 사용되는 것이 게터와 세터이다. 이는 프라이빗 변수의 값을 추출하거나 변경할 목적으로 접근하도록 해주는 함수이다.

class Circle:
	def get_radius(self):
		return self.__radius
	def set_radius(self, value):
		self.__radius = value

위 두 함수가 게터와 세터이다.

파이썬 언어는 게터와 세터를 쉽게 만들고 사용할 수 있게 하는 기능을 제공한다.

class Circle:
	@property
	def radius(self):
		return self.__radius
	@radius.setter	#변수이름.setter
	def radius(self,value):
		self.__radius = value

위와 같은 방식으로 데코레이터를 사용하면 인스턴스.radius를 통하여 프라이빗 변수의 값을 변경하거나 꺼내올 수 있다.

상속

class Parent:
	def __init__(self):
		...

class Child(Parent):
	def __init__(self):
		Parent.__init__(self)

child = Child()

위 코드처럼 상속으로 클래스를 생성할 수 있다.
이처럼 상속으로 클래스를 생성한 경우 Parent의 __init__()가 호출되고, 이후 Child의 __init__()가 실행된다.

class CustomException(Exception):
	def __init__(self):
		Exception.__init__(self)
	def __str__(self):
		return "오류 발생"
raise CustomException

__str__()함수는 부모클래스에도 정의가 되어있다. 이처럼 부모 클래스에 정의되어 있는 함수를 자식에서 다시 정의하는 것을 재정의 또는 오버라이드라고 부른다.

태그:

카테고리:

업데이트:

댓글남기기