Skip to content

Latest commit

 

History

History
242 lines (200 loc) · 9.91 KB

211102.md

File metadata and controls

242 lines (200 loc) · 9.91 KB

Day 32

한 권으로 개발자가 원하던 파이썬 심화 A to Z

예약어

keyword 모듈은 예약어 관리 모듈이다.

import keyword

kwlist는 예약어를 리스트로 관리한다.

len(keyword.kwlist) # 예약어가 몇 개 있는지 확인

문자열

파이썬은 유니코드 문자에 있는 다양한 언어로 변수를 정의할 수 있다.

import string # 문자열 모듈

문자열 모듈에 있는 정보 확인

count = 0
for i in dir(string): # dir()은 어떤 객체를 인자로 넣어주면 해당 객체가 어떤 변수와 메소드를 가지고 있는지 나열해준다.
    print(i, end=", ")
    count += 1
    if count % 5 == 0: # 한 줄에 5개만 출력하도록 해줌
        print()

모듈의 주요 변수를 확인하는 것도 가능하다.

string.ascii_letters # 알파벳 소문자부터 대문자까지 출력된다.

string.digits # 0부터 9까지의 숫자가 출력된다.

string.puctuation # 문장을 작성할 때 필요한 다양한 기호가 출력된다.

string.whitespace # 공백문자를 출력한다. (\n, \t, ...)

내장 이름공간과 전역 이름공간

파이썬이 설치되면 자동으로 제공되는 함수와 클래스는 __builtins__에서 관리한다.
import 하지 않고 내부함수와 클래스를 사용하는 것이 특징

__builtins__ #<module 'builtins' (built-in)> 출력

모듈 내 정의된 모든 변수를 관리하는 영역을 전역 이름공간(global namespace)이라고 한다.
내장함수 globals는 전역 이름공간을 조회해서 딕셔너리로 반환한다.

i = 100
globals()['i'] # 100 출력

내장함수 vars는 전역 이름공간에 저장된 변수를 조회한다.

vars()['i']

함수 정의문의 실행하면 함수를 사용할 수 있게 로딩한다.

로딩 순서

  1. 함수 이름을 변수 이름으로 지정
  2. 로딩된 함수 객체를 값으로 할당

이 방식은 변수를 정의하고 값을 할당하는 것과 같은 방식으로 전역 이름공간에 함수를 저장하게 된다.
그래서 globals 함수로 함수 이름을 조회하면 함수 객체를 출력한다.

def add_(x, y):
    return x + y

globals()['add_'] # <function __main__.add_(x, y)> 출력

함수가 가진 전역 이름공간을 __globals__ 속성을 사용하면 확인할 수 있다. __globals__속성에 변수 이름을 문자열로 전달하면 저장된 값을 조회할 수도 있다.

add.__globals__['i'] # 100 출력

globals함수와 __globals__는 레퍼런스가 같아 같은 객체이다.

표현식

덧셈 연산자는 2개의 항을 더하는 이항 연산자로 하나의 값을 반환한다.
파이썬의 연산자는 프로그램을 표기할 때와 내부에서 실행될 때 다르게 처리된다.
실제 연산자를 실행할 때는 각 클래스 내부에 정의된 스페셜 메소드로 변환해서 실행한다.

a = 100
a.__add__(200) # 300 출력, 덧셈 연산자 스페셜 메소드

b = "문자"
b.__add__("열") # "문자열" 출력, 문자열 클래스도 __add__ 사용 가능

연산자와 스페셜 메소드

__add__

(1).__add__(1) # 정수 1 객체에 스페셜 메소드 __add__에 정수 1을 인자로 전달해서 실행

int.__add__(1, 1) # 2 출력, 클래스에서 스페셜 메소드에 두개의 정수를 인자로 전달해서 실행

뺄셈이나 곱셈 연산자도 계산 가능하다.
하지만 __sub__, __mul__는 반드시 2개의 인자를 전달해야 한다.

int.__sub__(1, 1) # 0 출력

int.__mul__(2, 3) # 6 출력

나눗셈은 연산자가 두 개가 있다.

  • __truediv__(연산자 /) : 몫까지 다 계산
  • __floordiv__(연산자 //) : 나머지를 계산하지 않음
int.__truediv__(2, 2) # 1.0 출력

int.__floordiv__(2, 2) # 1 출력

연속 할당, 문자열로 작성된 것을 실행하기

표현식이나 문장을 바로 계산해서 결과를 반환하거나 내부에 바로 사용할 수 있게 구성하는 것을 탐욕스러운 평가(greedy evaluation) 또는 엄격 평가(eager evaluation)라고 한다.

a = b = c = d = 5
a.__add__(b).__add__(c).__add__(d) # 20 출력

가장 오른 쪽의 변수 할당인 d = 5가 실행되고 c = d가 실행되는 순서로 간다.
연산자를 연속해서 사용하면 내부적으로 스페셜 메소드를 연속으로 실행해서 처리하는 것과 같다.

문자열로 작성된 표현식 실행

e = "100 + 100"
eval(e) # 200 출력

eval()은 문자열 내의 표현식을 실행하는 내장함수이다.

문자열로 된 문장 실행

s = """
def add_(x, y):
    return x + y
"""

exec(s) # 함수가 정의된 문자열을 실행

add_(10, 10) # exec 함수가 실행되면, add_ 함수가 만들어지고 이를 호출해서 실행할 수 있다.

exec()은 문자열로 만들어진 문장을 실행하는 내장함수이다.

특정 객체를 만든 후에 실행

특정 표현식이 실행되면 결과값을 바로 반환하지 않고 이 값을 호출할 수 있는 값을 반환하는 객체를 핸들러(handler)라고 한다.
handler를 필요한 시점에 실행해서 결과를 반환하는 처리 방식을 지연 평가(Lazy evaluation)라고 하고, 보통 파이썬은 동적 객체를 만드는 반복자(Iterator)인 경우 handler 객체를 반환한다.
반복자 객체는 모든 원소를 다 사용한 후에는 다시 객체를 만들어서 사용해야 한다는 특징이 있다.

r = range(5)

for i in r:
    print(i)

문자열에 수식 넣고 계산

x = 100
y = "2 *x ** 2 + 4"
eval(y) # 20004 출력

z = "y1 = 2 *x ** 2 + 4"
exec(z)
globals()['y1'] # 20004 출력, 변수가 할당되면 전역 이름공간에서 조회 가능

변수가 객체를 바인딩한 후 자료형 결정

변수는 실행할 때 값을 보관해서 관리하는 단순한 역할만 수행한다.
변수에 값을 할당해서 변수를 정의하면 실제 변수에 객체가 할당되고, 이를 변수에 객체를 바인딩한다고 한다.
변수에 특별한 자료형을 지정하지 않아도 객체의 정보를 확인해서 클래스 정보를 처리할 수 있다.
즉, 객체 할당이 자료형을 결정하는 것이고, 이런 방식을 동적 자료형이라고 한다.
파이썬의 모든 객체는 해당하는 클래스가 있고, 클래스를 만든 후에 객체를 생성해서 처리하므로 객체에 대한 자료형이 항상 결정되어 강한 자료형 체계를 유지한다.

동적 자료형 처리

var = [] # 변수에 빈 리스트 객체를 할당, 변수가 만들어진다.

type(var) # list 출력, 변수에 바인딩된 객체의 자료형 확인(속한 클래스 확인)

var.__class__ # list 출력, 객체 내부에 있는 속성 __class__를 조회하면 클래스를 확인할 수 있다.

강한 자료형 처리

c = int('100') # int 클래스를 사용해서 정수 객체를 만든다.

c # 변수를 참조해서 값을 조회한다.

type(c) # 객체의 자료형을 type 클래스에 변수를 전달해서 확인한다.

보통 강한 자료형은 같은 클래스로 만들어진 객체일 때만 연산을 실행하고 다른 클래스로 만들어진 객체인 경우 연산이 불가능하다.
해석하면 다른 자료형끼리의 연산은 보통 불가능하다는 뜻인 것 같다.

함수와 메소드

class A(object): # 예약어 + 이름 + 상속관계 + : 로 작성
    def func(self):
        print("func")

A.func # <function __main__.A.func(self)> 출력, function 객체임을 확인 가능하다.

a = A() # 클래스 생성자로 객체를 만들어서 변수에 할당

a.func # <bound method A.func of ~~~> 출력, 메소드로 변환되었음을 확인 가능하다.

파이썬은 클래스에 정의된 함수와 객체에서 함수를 바인딩할 때 메소드로 변환한다.

객체의 원소에 대한 변경 여부

변경할 수 없는 자료형이 있다.
파이썬 문자열 클래스로 만들어진 객체는 여러 문자열을 원소로 가질 수 있으나, 내부 원소를 변경할 수 없다.

var = "문자열"
var[0] = "가" # 에러 발생, 내부에 할당하는 메소드가 없다.

문자열 클래스는 메소드가 실행되면 새로운 문자열 객체를 만들어서 반환한다.
replace 메소드는 기존 문자열이 변경되는 것이 아닌 새로운 문자열을 만들어서 변경한 것처럼 만들어 주는 것이다.

변경할 수 있는 자료형
여기서 변경할 수 있다는 것은 내부의 원소를 변경, 삭제, 추가할 수 있음을 의미한다.

l = [1, 2, 3, 4]
l[0] = 100 # l의 첫 번째 요소를 100으로 변경
l.__setitem__(0, 999) # 스페셜 메소드 사용, 첫 번째 요소(0번 인덱스)를 999로 변경한다.

다른 객체를 생성하는 형 변환(type casting)

파이썬에서 형 변환은 새로운 클래스의 객체를 만드는 것이다.

s = '100' # 문자열 '100'을 변수에 할당

i = int(s) # int 클래스로 객체를 생성하고 형 변환

변경 가능 여부 확인

객체를 변경할 수 있다는 것은 변경할 수 있는 함수로 클래스를 정의했다는 뜻이다.

클래스에는 속성과 함수 등을 관리하는 이름공간인 __dict__가 생성된다.

str.__dict__['__getitem__'] # 문자열 클래스의 이름공간 __dict__내에서 __getitem__ 스페셜 메소드 조회

str.__dict__['__setitem__'] # 문자열 객체는 변경할 수 없어서 __setitem__ 스페셜 메소드가 정의되어 있지 않아 에러 발생

내장 클래스 list는 변경과 삭제가 가능한데, 이 말은 __getitem__, __setitem__, __delitem__이 모두 작성되어 있다는 것이다.

list.__dict__['__getitem__']
list.__dict__['__setitem__']
list.__dict__['__delitem__']