사실 수치계산/데이터분석을 위해 파이썬을 계속사용하여 왔다. 하지만 아직 컴파일러 언어에 익숙한 까닭으로 인해 파이썬을 파이써닉하게 사용하지 않았다. 또 주로 배열과 리스트를 많이 사용하였고 딕셔너리나 튜플자료형을 사용하지 않았던 것 같다. 따라서 다시 파이썬을 기초부터 공부하기로 하고, 기초 문법 및 여러가지 알아두면 좋을 것들을 정리하고자 한다. 또 평소에 사용하면서 공부했으면 좋겠다고 생각한 것들 역시 정리하고자 한다.
변수 및 자료형
a=100
b=a
print(id(a), id(b))
>>> 9792160 9792160
이와 같이 a와 b의 메모리 주소는 동일하다. 다만, 다음에 b에 다른 값을 덮어씌우면 b의 값과 메모리 주소는 변경될 것이다. 이번에는 리스트를 예로 들면 좋을 것 같다.
a=[1,2,3]
b=a
b[2]=4
print(a)
>>> [1,2,4]
print(b)
>>> [1,2,4]
위에서 살펴본 것과 같이 변수를 복사할 때와 마찬가지로 리스트를 복사할 때에도 같은 메모리 주소를 공유하는 것을 확인할 수 있다. 그렇다면 슬라이싱을 사용하여 리스트를 복사하여 보도록 한다.
a=[[1,2],[3,4]]
b=a[:]
print(id(a), id(b))
>>> 140728233274880 140728233280448
print(id(a[0]), id(b[0]))
>>> 9788992 9788992
a[0].append(3)
print(a,b)
>>> [[1, 2, 3], [3, 4]] [[1, 2, 3], [3, 4]]
슬라이싱을 사용하면 리스트 a와 b의 메모리 주소는 변경되는 것을 볼 수 있으나, 여전히 리스트 원소들의 메모리 주소는 동일한 것을 확인할 수 있다. 따라서 a[0]에 append 함수를 사용할 경우에 a와 b리스트 모두 동일하게 적용되는 것을 확인할 수 있다.
import copy
a=[[1,2], [3,4]]
b=copy.copy(a)
print(id(a), id(b))
>>> 140728233274880 140728233280448
print(id(a[0]), id(b[0]))
>>> 9788992 9788992
a[0].append(3)
print(a,b)
>>> [[1, 2, 3], [3, 4]] [[1, 2, 3], [3, 4]]
copy 함수를 사용하여 복사를 수행하더라도 얕은 복사(shallow copy)가 수행되는 것을 확인할 수 있다. 각 상황에 따라서 이러한 코드가 도움을 줄 수 있으나, 그렇지 않은 경우라면 깊은 복사(deep copy)를 수행하여야 한다.
a=[[1,2], [3,4]]
b=copy.deepcopy(a)
print(id(a), id(b))
>>> 140728232780096 140728233282432
print(id(a[0]), id(b[0]))
>>> 140728232780608 140728232749120
a[0].append(3)
print(a, b)
>>> [[1, 2, 3], [3, 4]] [[1, 2], [3, 4]]
깊은 복사는 copy 모듈의 deepcopy 함수를 사용함으로써 사용이 가능하고, 복사 대상의 원소 메모리 주소도 변경되는 것을 확인할 수 있다. 따라서 추후에 a 리스트의 원소를 변경한다고 하더라도 b 리스트에는 영향을 주지 않는 것을 확인할 수 있다.
딕셔너리형
mydict={}
mydict["name"]="kimjy"
mydict["major"]="CS"
print(mydict)
>>> {'name': 'kimjy', 'major': 'CS'}
- 딕셔너리는 key:value 쌍으로 이루어진 자료구조임.
print("name" in mydict.keys())
>>> True
print("kimjy" in mydict.values())
>>> True
- 위와 같이 key 혹은 value가 딕셔너리 안에 존재하는 지를 확인할 수 있음
집합
a={1,2,3}
print(a)
>>> {1,2,3}
a={1,2,3,1}
print(a)
>>> {1,2,3}
- 집합 자료형은 원소의 중복이 허용되지 않음
튜플
a=(1,2,3)
a=tuple([1,2,3])
- 리스트와 유사하나 튜플은 값이 변하지 않음
함수
def foo(a, b):
return a-b
foo(2,1)
foo(a=2, b=1)
이와 같이 순서대로 a,b를 입력해도 되고, a=a1, b=b1으로 입력하여도 된다.
def foo(a, b=1):
return a-b
foo(2)
혹은 이와 같이 b에 default argument를 설정하여서 b를 입력받지 않고도 계산이 가능하게 할 수 있다. 단 dufault argument는 argument들의 마지막에 위치하여야 한다.
def foo(*args):
def foo(*kwargs):
위와 같이 함수의 인자를 튜플(args)이나 딕셔너리(kwargs)로 넘겨받을 수 있다.
def foo(arg1, arg2, *args):
단 위와 같이 args가 나중에 와야 하며, args가 먼저 위치하면 에러가 발생한다. 아마 agrs가 먼저 위치하면 파이썬 인터프리터가 모든 인자들을 args로 인식하기 때문에 발생하는 에러인 것 같다.
class
객체지향 프로그래밍에 대한 지식은 있지만, 절차지향 프로그래밍 언어(Fortran 그리고 C)에 익숙하기도 하고, 전공인 병렬처리 분야에서 객체가 많이 사용되지는 않은 까닭으로 인해 크게 사용한 경험이 없다. 따라서 객체지향 프로그래밍에 대해 정리하여 놓는다면 나중에 사용할 때 큰 도움이 될 것이라고 생각한다. 또 용어정리를 미리 해두어야 추후 업무에 사용할 때 혼동이 생기지 않을 것이라 생각한다.
파이썬에서 class는 아래와 같이 선언한다.
class MyObject:
def __init__(self, arg1, arg2):
self.result=0
self.arg1=arg1
self.arg2=arg2
def add_1(self, arg3, arg4):
self.result = self.arg1+self.arg2+arg3+arg4
- 여기서 self라는 매개변수를 사용하였는데, self는 자기 자신을 참조하는 매개변수이다.
(자바의 this가 파이썬의 self와 유사하다고 한다.)
tester=myobject(2,3)
print(tester.add1(4,5))
>>> None
print(tester.result)
>>> 14
- 위에서 작성한 myobject 클래스를 사용하여 tester라는 이름을 갖는 인스턴스를 생성하였다.
(인스턴스: class 정의로부터 실제 객체를 생성한 것) - class 내부에서 작성한 add1 메서드를 호출하였는데, 따로 return 값을 지정하지 않았으므로 None이 출력되는 것을 확인할 수 있다.
(메서드: 클래스에서 정의한 함수, 클래스의 함수라고 생각하여도 무방) - 최종적으로 tester.add1()이 업데이트한 tester.result를 출력하여 값이 잘 반영된 것을 확인할 수 있다.
기타
잘 쓰지 않아서 가끔 인터넷에 찾아보고자 하는 것들도 정리하고자 한다.
var +=1
var -=1
- += 혹은 -=를 사용하면 var=var+1을 축약하여 사용할 수 있다.
- %을 사용하면 mod 연산이 가능
while i< 10:
i+=1
i가 10 미만일 때 까지 반복을 수행
'python' 카테고리의 다른 글
전문가를 위한 파이썬 책 구매 (0) | 2022.07.21 |
---|---|
파이썬 기반의 멀티프로세싱 (0) | 2021.12.15 |
closure & decorator (0) | 2021.12.15 |
병렬처리 특성 비교, 그리고 파이썬 기반의 멀티쓰레딩 (0) | 2021.12.06 |
PEP 8 - 파이썬 코드 스타일 가이드 (0) | 2021.12.06 |