Developer

Python 본문

Programming Language/Python

Python

DPhater 2021. 1. 19. 19:30
  • 플랫폼(OS) 독립적인 인터프리터 언어

    • 보통 소프트웨어는 플랫폼에 의존적이기 때문에 OS마다 작동되는 소프트웨어가 다르다. 각 OS에 맞는 인터프리터(해석기)를 사용해서 해당 OS에 맞는 소프트웨어를 작성해야 한다.
    • 하지만 Python은 OS에 독립적이기 때문에 어떤 OS던지 상관없이 사용할 수 있다.
  • 객체지향 언어

    • 기능, 속성을 가지고 있는 객체를 만들어 이 객체들이 상호작용을 하도록 프로그램을 작성할 수 있는 언어
  • 동적 타이핑 언어

    • 프로그램이 실행하는 시점에 프로그램이 사용할 데이터에 대한 타입을 결정
  • 인터프리터 <> 컴파일러

    • 컴파일러

      = 소스코드를 기계어로 번역해 해당 플랫폼에 최적화되어 프로그램을 실행

      = 실행 속도가 빠름, 한 번에 많은 기억 장소가 필요

    • 인터프리터

      = 번역 과정 없이 소스코드 실행 시점에 해석하여 컴퓨터가 처리할 수 있도록 함

      = 메모리가 적게 필요하고 실행 속도가 느림

문법

지금까지 배워왔던 언어에서는 중괄호를 사용해 코드 블록을 나누고 하나의 구문이 끝날 때 세미콜론(;)을 달아주었다. 하지만 파이썬의 경우 세미콜론을 안 써도 되고, 들여 쓰기로 코드 블록을 나눈다.

변수

위의 예시에서 a와 b와 같이 특정 값을 저장할 수 있는 것이 변수이다. C 혹은 JAVA와 같은 언어를 배울 때에는 int a, double a와 같이 앞에 자료형을 명시해야 했지만 Python은 동적 타이핑 언어이기 때문에 자료형을 따로 명시해주지 않아도 된다.

물론 계산한 결과를 다른 변수에 저장하는 것도 가능하고, 숫자뿐만 아니라 문자 혹은 문자열도 같은 방식으로 사용이 가능하다. C++의 string을 사용하는 것처럼 문자열을 +연산자를 사용해 합칠 수 있다.

문자열

이전에 배웠던 언어에서는 문자열은 ""(큰따옴표) 문자는 ''(작은따옴표)를 사용해 표시하였지만 Python에서는 문자열을 나타낼 수 있는 방식이 다양하다.

"string"

'string'

"""string string string"""

'''string string string'''

+연산자도 C++의 string처럼 사용할 수 있고, *연산자는 문자열을 반복할 수 있다.

print("x" * 10)는 x를 10번 출력해준다. 물론 이런 식으로 저장한 문자열을 index로 접근이 가능하다. 이전에 배웠던 언어와의 차이는 a = "abcdef"에서 a [-1]은 뒤에서 첫 번째('f') 문자를 가리킨다. 또 다른 문자열 사용방법으로 slicing기법이 있는데 a [0:4]처럼 사용하여 0번 index부터 3번 인덱스에 있는 문자열("abcd")을 사용할 수 있다. slicing기법에도 여러 가지 방법이 있다.

a [3:] : 3번 index에서 끝까지

a [:6] : 0번 index에서 6번 이전까지

a [:] : 전체

string의 경우 immutable type이라 각 값을 수정할 수없다. (a [3] = 'a'와 같이 사용 불가능)

string을 변경하고 싶을 경우 slicing을 사용하거나 list를 사용하거나 replace를 사용해야 한다.

  • list를 사용하는 방법
    a = 'abcdef' 
    a = list(a) 
    a[0] = 'xx' 
    print(''.join(a)) # xxbcdef
  • replace를 사용하는 방법
    a = 'abcdef' 
    print(a.replace('d', 'x')) # abcxef
  • slicing을 사용하는 방법
    a = 'abcdef'
    print(a[:3] + 'xx' + a[4:]) # abcxxef

mutable, immutable

  • mutable객체의 복사

    list1 = [1, 2, 3]
    list2 = list1 
    list2[0] = 5 
    # list1 = [5, 2, 3] 
    # list2 = [5, 2, 3]

    list를 그냥 할당하면 얕은 복사가 일어난다. 같은 메모리 주소를 가리키고 있기 때문에 list 2를 변경하면 list 1도 같이 변하게 된다. dict이나 set에서도 같은 동작을 한다.

    slicing을 사용해 새로운 list에 현재 리스트를 할당할 경우(list2 = list1[:]) 서로 다른 list가 되지만 만약 list 내부의 값이 mutable일 경우 역시 얕은 복사가 이루어 지게 된다. list자체는 다른 주소를 가리키고 있지만 내부의 mutable 한 객체가 같은 주소를 가리키게 되기 때문이다.

  • immutable객체의 복사

    a = "string"
    b = a 
    b = "new string" 
    # a = "string"
    # b = "new string"

    immutable의 경우 처음 할당에서(b = a) mutable의 할당과 같이 같은 주소를 가리키고 있다. 하지만 b에 다른 값을 넣었을 때 (b = "new string") 재할당이 이뤄지며 서로 다른 값을 가지게 된다.

  • copy.deepcopy를 사용해 내부 객체까지 새롭게 복사하는 깊은 복사를 할 수 있다.

  • 혹은 생성자를 사용해 복사하면 된다. (a = list(b))

리스트

fruit = ['apple', 'banana', 'strawberry', 'orange'] fruit라는 변수에 []를 사용해서 여러 과일들을 넣어줄 수 있다. print(fruit)처럼 list를 한 번에 출력할수도있다. 문자열과 마찬가지로 index로 사용할 수있고 slicing기법도 사용할 수 있다. fruit[1:2] = ['watermelon', 'kiwi'] 처럼 리스트 중간에 삽입을 할 수도 있다. fruit = fruit + ['watermelon', 'kiwi'] 처럼 뒤에 새로운 리스트를 추가할 수 있다. 하나의 자료형만 담을 수 있는것이 아닌 llist = [1, 'abc', 0.3]과 같이 다양한 자료형을 한번에 담을 수 있고, llist = [[1, 2] ['a', 'b']]와 같이 중첩해서 list를 작성할 수 도 있다.(llist [0][0]과 같이 사용 가능)

  • Append함수

    numbers = [1, 2, 3, 4, 5] 
    numbers.append(6) # numbers = [1, 2, 3, 4, 5, 6]
  • Remove함수

    numbers = [1, 2, 3, 4, 5] 
    numbers.remove(3) 
    # numbers = [1, 2, 4, 5]

    remove의 경우 list내부에 없는 값을 작성하면 안 된다.

  • Length함수

    numbers = [1, 2, 3, 4, 5] 
    numbers_length = len(numbers) # 5
  • Join 함수

    numbers = [1, 2, 3, 4, 5]
    "".join(numbers) # 12345
  • Split 함수

    numbers = '1:2:3:4:5'
    numbers.split(':') # numbers = [1, 2, 3, 4, \]
    # 인자로 넣어준것을 기준으로 문자열을 list로 만들어준다. 
    # 공백일 경우 Space기준으로 나누어 list로 만든다.

튜플

튜플은 리스트와 비슷하지만 한 번 생성되면 값을 변경할 수 없다. 튜플의 경우 ()를 통해 사용할 수 있다. index로 접근할 수있고, +연산으로 값을 추가 *연산으로 값을 반복할 수있다. ()내부에 하나의 값만 들어있다면 튜플이 되지않는다. (하나의 값만 넣고싶을 경우 ,(콤마)를 작성해주면 tuple로 사용할 수있다.) 또한 튜플의 경우 괄호를 생략할 수있다.

tu = (1, 2, 3, 4) 
tu1 = 1, 2, 3, 4 
type(tu) # tuple 
type(tu1) # tuple

튜플의 경우 값을 삭제하거나 변경할 수 없다. 따라서 tu[0] = 4 혹은 del tu[0] 은 TypeError가 발생한다.

또한 튜플을 사용하여 한번에 변수에 할당할 수 있다.

a, b, c = (1, 2, 3) 
# a = 1 
# b = 2 
# c = 3

딕셔너리

key, value형식을 저장하는 자료형이다. 딕셔너리의 경우{} 안에 Key:value의 쌍을 지정해 사용할 수 있다. dic = { 'A' : 1, 'B' : 2, 'C' : 3}

list 중 arr = [[1,2], [3,4], [5,6]]과 같이 두 값으로 이루어진 중첩 list의 경우 dict를 사용해 딕셔너리로 변환이 가능하다. 하지만 순서를 보장해주지는 않는다.

  • 딕셔너리 추가와 변경

    dic = {'A' : 1, 'B' : 2, 'C' : 3} 
    dic['D'] = 4 # dic = {'A' : 1, 'B' : 2, 'C' : 3, 'D' : 4} 
    dic['A'] = 0 # dic = {'A' : 0, 'B' : 2, 'C' : 3, 'D' : 4}

    없는 Key라면 추가되고 있는 Key라면 value가 변경된다.

  • 딕셔너리 삭제

    dic = {'A' : 1, 'B' : 2, 'C' : 3}
    del dic['A'] # dic = {'B' : 2, 'C' : 3}
    dic.clear() # dic = {}

    위의 코드처럼 특정 Key값을 삭제할 수 있다. 하지만 해당 키값이 딕셔너리 내부에 존재하지 않으면 KeyError가 발생한다.

  • 특정 Key의 value 얻기

    dic = {'A' : 1, 'B' : 2, 'C' : 3}
    dic['A'] # 1

    딕셔너리 삭제와 마찬가지로 존재하지 않는 키로 사용할 경우 KeyError가 발생한다.

  • Key의 존재 확인

    딕셔너리 삭제 및 value 얻기 에서 나오는 Error를 막기 위해 del 하기 이전에 지우려는 Key가 딕셔너리 안에 존재하는지 먼저 확인을 해야 한다.

    #1 
    'A' in dic # 'A'가 dic안에 있을 경우 true 없을 경우 false반환 
    #2 
    dic.get('AAAA') # AAAA가 dic내부에 없을 경우 None가 된다. 
    dic.get('AAAA', 'not exist') # AAAA가 dic내부에 없을 경우 not exist가된다.
  • 딕셔너리 결합

    하나의 딕셔너리를 복사해 다른 딕셔너리에 추가한다. (같은 Key가 존재할 경우 원본 딕셔너리가 수정된다.)

    dic1 = {'A' : 1, 'B' : 2, 'C' : 3} 
    dic2 = {'D' : 4, 'E' : 5, 'A' : 0} 
    dic1.update(dic2) # dic1 = {'A' : 0, 'B' : 2, 'C' : 3, 'D' : 4, 'E' : 5}
  • 존재하는 모든 Key 얻기

    dic = {'A' : 1, 'B' : 2, 'C' : 3} 
    dic.keys() # dict_keys(['A', 'B', 'C'])
  • Key value쌍 얻기

    dic = {'A' : 1, 'B' : 2, 'C' : 3} 
    list(dic.items()) # [('A', 1), ('B', 2), ('C', 3)] # 튜플로 반환된다.

set

set은 순서가 없고 내부의 값들은 고유하다. set의 경우 딕셔너리와 마찬가지로 ()를 사용해 표시하고, key가 없이 value만 존재한다. set은 mutable 한 값을 내부 원소로 가질 수없다. 같은 값을 추가할 경우 자동적으로 삭제가 된다. set을 원소 없이 생성하고 싶다면 생성자를 사용해야 한다.

s = {} 
type(s) # dict 
s = set() 
type(s) # set
  • 원소 추가

    s = {1, 2, 3, 4, 5} 
    s.add(6) # s = {1, 2, 3, 4, 5, 6} 
    s.add(5) # s = {1, 2, 3, 4, 5, 6}

    같은 값을 추가할 경우 추가되지 않는다.

  • 원소 제거

    s = {1, 2, 3, 4, 5}
    s.remove(3) # s = {1, 2, 4, 5} 
    #dict list와 마찬가지로 없는 원소로 remove를 사용하면 KeyError가 발생한다. 
    s.discard(21312) 
    #discard를 사용하면 없는 원소여도 KeyError가 발생하지 않는다.
  • 합집합

    |연산자를 사용하거나 union함수를 사용할 수 있다.

    s1 = {1,2,3} 
    s2 = {2,4,5}
    s3 = s1.union(s2) # s3 = {1,2,3,4,5}
  • 교집합

    &연산자를 사용하거나 intersection함수를 사용할 수 있다.

    s1 = {1,2,3} 
    s2 = {2,4,5}
    s3 = s1.intersection(s2) # s3 = {2}
  • 차집합

    -연산자를 사용하거나 difference함수를 사용할 수 있다.

    s1 = {1,2,3}
    s2 = {2,4,5} 
    s3 = s1.difference(s2) # s3 = {1,3}
  • 합집합 - 교집합(대칭 차집합)

    ^연산자를 사용하거나 symmetric_difference함수를 사용할 수 있다.

    s1 = {1,2,3}
    s2 = {2,4,5} 
    s3 = s1.symmetric_difference(s2) # s3 = {1,3,4,5}

for반복문

Python의 경우 for a in b의 형식으로 for문을 사용한다. iterable 한 개체의 경우

a = [1,2,3,4,5,6] for v in a: 
	print(v) 
    
##output 
#1 
#2
#3
#...

위와 같이 사용할 수 있다. dict의 경우 이런 식으로 반복하게 되면 Key만 출력되는데

for v in dic.values()와 같이 values를 사용해 key만 for key, val in dic.items()와 같이 items를 사용해 key, value쌍을 반복할 수 있다.

dic ={'A' : 1, 'B' : 2} 
for key, val in dic.items(): 
	print("{key},{value}".format(key=key,value=val))
    
##output 
#A,1 
#B,2

또한 for i in range(5)와 같이 range를 사용해 반복할 수 있다. range의 경우 range(시작 숫자, 종료 숫자, step)의 형태이다.

  • enumerate

    enumerate를 사용하면 몇 번째 반복문인지 확인할 수 있다.

    a = [1,2,3] 
    for v in enumerate(a):
    	print(v) 
        
    ##output 
    #(0,1)
    #(1,2)
    #(2,3)
    #enumerate이 튜블 형태를 반환하므로 
    for index, v in enumerate(a): 
    	print("{} , {}".format(index,v)) # 의 형태로 index값을 따로 받아올 수있다.

파일 입출력

파이썬에서는 open함수를 제공한다. f = open("PATH", mode) mode는 r, w, a가 있다.

##파일에 쓰기 
#1 
numbers = [1, 2, 3, 4] 
with open('test.txt', 'w') as f: 
    for v in numbers: 
        f.write(v + "\n") 

#2 
numbers = [1, 2, 3, 4] 
f = open('test.txt' , 'w') 
for v in numbers: 
    f.write(v + "\n") 

##파일에서 읽기 
#1 
f = open('test.txt', 'r') 
contents = f.readlines() ## 파일의 모든 줄을 list형태로 읽어옴 

#2
with f = open('test.txt', 'r') as f: 
    for line in f: 
        print line, #,를 붙혀 개행 하나를 무시

#3 
f = open('test.txt', 'r') 
contents = f.read() ## 파일의 모든 내용을 string형태로 읽어옴

함수

def function_name(parameter):
	.... 
    return .. # 리턴값이 있다면

함수의 경우 지금까지의 다른 언어들과 유사하다. C++에서 처럼 인자의 default값을 미리 정할 수 있다.

def function_name(first, seoncd = false): 
	...
  • call by reference

    파이썬에는 global 키워드를 사용해 함수를 호출한 곳의 변수에 영향을 끼칠 수 있다.

    a = 3 
    def add_one(): 
        global a 
        a += 1 
    add_one()
    print(a) 
    ##output 
    #4

클래스

클래스의 경우 C++와 큰 차이가 없는 것 같다. this대신 self를 사용하는 정도?

class Test: 
    def __init__(self, first, second): #클래스 멤버 초기화 
        self.a = first 
        self.b = second 

    def __new__(): 
        ... 

    def member_function(self): 
        #멤버 함수 ...

init 은 생성자라고 생각하면 된다. 실제 객체를 생성할 때 (my = Test()) __new__함수가 호출되어 할당을 하고 이후에 __init__을 호출해 초기화를 한다고 한다. 작성한 클래스에 __new__함수가 없다면 object클래스에 정의된 __new__가 호출된다고 한다(allocator라고 생각하면 되는 건가??).

__new__작성하기

'Programming Language > Python' 카테고리의 다른 글

Python(문자열 함수, IO, 함수)  (0) 2021.01.19
Comments