10 Sep 2017 » python

2017-09-10-python_1

객체지향 프로그래밍 ①

다음 어휘를 익혀보자.

클래스(class)

python이 새로운 자료형을 만들도록 한다.

객체(object)

가장 기초적인 자료형 또는 어떤 자료형의 인스턴스를 의미한다.

def

함수를 정의하는 방법

self

클래스의 함수 안에서 사용.

접근한 인스턴스 / 객체를 가리키는 변수

상속(inheritance)

한 클래스가 다른 클래스의 특성(trait)을 자식이 부모에게 물려받듯 상속한다는 개념이다.

합성(composition)

한 클래스를 다른 클래스의 일부로 합성할 수 있다는 개념이다.

속성(attribute)

클래스가 가진 속성(property)으로, 보통 합성으로 생기고 변수 형태이다.

is-a

'연어'is-a'물고기'처럼 한 항목이 다른 항목을 상속했다는 뜻의 문구이다.

has-a

'연어'has-a'입'처럼 한 항모이 다른 항목을 합성했거나 어떤 특성(trait)을 가졌다는 뜻의 문구이다.


문장을 연습해보자.

아래 코드가 의미하는 것을 적어보자.

In [ ]:
class X(Y):

"X 클래스라는 Y의 일종(X is-a Y)을 만든다"

In [ ]:
class X(object):
    def __init__(self, J)

"X 클래스는 self와 J 매개변수를 받는 __init__을 가졌다."

(X 클래스 has-a __init__)

In [ ]:
class X(object):
    def M(self, J)

"X 클래스는 self와 J 매개변수를 받는 이름이 M인 함수를 가졌다."

(class X has-a 이름이 M인 함수)

In [ ]:
foo = X()

"foo 변수를 X 클래스의 인스턴스 하나로 정한다."

In [ ]:
foo.M(J)

"foo 변수에서 M 함수를 받아 self, J 매개변수를 넣어 호출한다."

In [ ]:
foo.K = Q

"foo 변수에서 K 속성을 받아 Q 값으로 정한다."

위의 X, Y, M, J, K, Q, foo가 있는 곳마다 빈 공간이 있는 것처럼 생각하고 치환하여 general하게 적용하자!


다음 코드를 리뷰해보자.

아래 코드는 클래스의 개념을 묻고 답하는 테스트를 해주는 스크립트이다.

전반적인 코드의 큰 틀은 다음과 같다.

  1. 클래스를 만드는 다양한 형태를 문자로 일반화 시킨 코드와 그 코드 해석을 딕트로 만든다.
  2. 코드가 문제가 될지, 코드 해석이 문제가 될지 선택할 수 있는 로직을 if문을 사용하여 추가.
  3. 일반화된 특수 문자를 단어로 교체하기 위해 단어 불러오기
  4. 특수문자를 단어로 바꿔주는 convert 함수 작성
  5. 실행 시 돌아가는 부분을 작성
    • 무한 loop(while True)를 활용
In [ ]:
# -*- coding: utf-8 -*-

import random
from urllib import request
from urllib.request import *
import sys

# key = class를 작성하는 코드 / value = 코드를 해석
## 이를 사전으로 만든다.
PHRASES = {
    "class %%%(%%%):":
    "%%% 클래스라는 %%%의 일종을 만든다.", # is-a
    "class %%%(object):\n\tdef __init__(self, ***)":
    "%%% 클래스는 self와 *** 매개변수를 받는 __init__을 가졌다.", # has-a
    "class %%%(object):\n\tdef ***(self, @@@)":
    "%%% 클래스는 self와 @@@ 매개변수를 받는 이름이 ***인 함수를 가졌다.", # has-a
    "*** = %%%()":
    "*** 변수를 %%% 클래스의 인스턴스 하나로 정한다.",
    "***.***(@@@)":
    "*** 변수에서 *** 함수를 받아 self, @@@ 매개변수를 넣어 호출한다.",
    "***.*** = '***'":
    "*** 변수에서 *** 속성을 받아 *** 값으로 정한다."
}


# 스크립트를 실행할때, argv가 두개 이고, 두 번째 argv가 "한국어"이면 코드 해석이 문제로 나온다.
## argv 없이 스크립트를 그냥 실행하거나, 3개 이상이면 코드가 문제가 코드해석을 답으로 써야 한다.
if len(sys.argv) == 2 and sys.argv[1] == "한국어":
    PHRASES_FIRST = True
else:
    PHRASES_FIRST = False

    
WORD_URL = "http://learncodethehardway.org/words.txt"
WORDS = []

# 웹사이트에서 단어를 불러온다.
for word in urlopen(WORD_URL).readlines():
    # 따옴표 안의 \n와 같은 탈출문자열 코드를 없애준다. 그래서 단어만으로 리스트를 만들 수 있다.
    WORDS.append(word.strip())


def convert(snippet, phrase):
    """class dict 안 기호('@@@' 등)를 단어로 변경"""
    # snippet에 "%%%"가 들어 있는 개수 만큼 WORDS list에서 단어를 랜덤하게 뽑고, 단어의 첫 글자를 대문자로 바꿔라.
    ## 그리고 그것을 list로 만들어라.
    class_names = [w.capitalize() for w in random.sample(WORDS, snippet.count("%%%"))]
    
    # snippet에 "***"가 들어 있는 개수 만큼 WORDS list에서 단어를 랜덤하게 뽑아라.
    other_names = random.sample(WORDS, snippet.count("***"))
    results = []
    param_names = []

    for i in range(0, snippet.count("@@@")):
        # param_count는 1, 2, 3 중 랜덤으로 뽑아라.
        param_count = random.randint(1,3)
        
        #  위에서 랜덤으로 정해진 param_count 개수 만큼 단어를 무작위로 뽑아라.
        ## param_names 리스트에 추가해라.
        param_names.append(', '.join(random.sample(WORDS, param_count)))

    for sentence in snippet, phrase:
        # sesntence 리스트를 첫 원소부터 마지막 원소까지 자르면서 복사해라.(슬라이싱하면서 리스트를 복사)
        result = sentence[:]

        # 가짜 클래스 이름
        for word in class_names:
            # "%%%"를 word로
            ## result.replace(old, new[, count]) -> str
            result = result.replace("%%%", "{}".format(word), 1)

        # 가짜 나머지 이름
        for word in other_names:
            result = result.replace("***", "{}".format(word), 1)

        # 가짜 매개변수 목록
        for word in param_names:
            result = result.replace("@@@", "{}".format(word), 1)

        results.append(result)

    return(results)

# Ctrl-D를 누를 떄까지 계속한다.

## input 생성
try:
    input = raw_input
except NameError:
    pass


try:
    while True:
        snippets = list(PHRASES.keys())
        # random.shuffle(리스트) 리스트가 들어가야 하므로 키값을 리스트로 변경시켜 주었다.
        random.shuffle(snippets)

        for snippet in snippets:
            phrase = PHRASES[snippet]
            question, answer = convert(snippet, phrase)
            
            # 만약 PHRASES_FIRST = True라면, 답과 질문을 바꿔주면 된다.
            if PHRASES_FIRST:
                question, answer = answer, question

            print(question)

            input(">")
            print("답: {}\n\n".format(answer))
except EOFError:
    print("\nBye")

urllib 모듈 안의 urlopen을 python-3에서 실행시키려면 아래의 request 모듈을 모두 실행시켜야 한다.

urlopen은 python-3 부터 request에 포함되므로 아래와 같이 request를 모두 import 해줘야 한다!

In [ ]:
from urllib import request
from urllib.request import *

word 정리

In [ ]:
WORDS = []

for word in urlopen(WORD_URL).readlines():
    print(word)
    print(word.strip())
    WORDS.append(word.strip())
    print(WORDS)

위 코드의 output은 위와 같다.

.strip()의 역할은 위에서 보듯이 \n와 같은 탈출문자열을 벗겨주는 기능을 한다.

터미널에서 실행은 다음과 같다.

In [ ]:
python oop_test.py

코드를 보고 코드 해석

In [ ]:
python oop_test.py 한국어

코드 해석을 보고 코드 작성


Reference

  • 깐깐하게 배우는 파이썬


Related Posts