developers Naver의 Open API 중 파파고 번역을 활용하여 번역하기

 

============================================================================

text문장 번역하기

 

from requests import Request, Session

clientId = "sMD9gukzyGkgBxN2xe4G"  # 애플리케이션 클라이언트 아이디값";
clientSecret = "eb7DgdcJMY"  # 애플리케이션 클라이언트 시크릿값";
apiURL = "https://openapi.naver.com/v1/papago/n2mt"
s = Session()
text = "안녕하세요. 오늘 기분은 어떻습니까?"
data = {
    'source': 'ko',
    'target': 'en',
    'text': text
}
headers = {
    "X-Naver-Client-Id": clientId,
    "X-Naver-Client-Secret": clientSecret
}
req = Request('POST', apiURL, data=data, headers=headers)  # 페이지 header값으로 요청을 하고 text 변환 코드를 전달

# 서버가 가진 클라이언트가 접속할 때 정보로 생성된 Session의 객체를 통해 값을 리턴받는다.
prepared = req.prepare()  # 서버와 연결할 1. 준비단계

res = s.send(prepared)  # 2. 세션을 통해 연결고리를 만든다. 데이터 변환 코드 전송

# 결과를 리턴받고 출력한다.
res_json = res.json()

print(res_json)
print(res_json["message"]["result"]["translatedText"])


#result
{'message': {'@type': 'response', '@service': 'naverservice.nmt.proxy', '@version': '1.0.0', 'result': {'srcLangType': 'ko', 'tarLangType': 'en', 'translatedText': 'Hello. How are you doing today?', 'engineType': 'N2MT', 'pivot': None}}}
Hello. How are you doing today?

 

============================================================================

.txt파일의 문장을 읽어와 번역해서 파일로 저장하기

 

# 파파고에서 어플리케이션을 등록하고 id와 pw를 받아서 한글문서를 번역해서 영어문서로 저장해보자.
from requests import Request, Session

clientId = "sMD9gukzyGkgBxN2xe4G"  # 애플리케이션 클라이언트 아이디값";
clientSecret = "eb7DgdcJMY"  # 애플리케이션 클라이언트 시크릿값";
apiURL = "https://openapi.naver.com/v1/papago/n2mt"
s = Session()

headers = {
    "X-Naver-Client-Id": clientId,
    "X-Naver-Client-Secret": clientSecret
}

file = open("mydata.txt", "r", encoding='UTF-8')
file_out = open("mydata_res.txt", "w", encoding='UTF-8')
while True:
    line = file.readline()
    data = {
        'source': 'ko',
        'target': 'en',
        'text': line
    }

    if not line:
        break

    file_out.write(line)
    req = Request('POST', apiURL, data=data, headers=headers)  # 페이지 header값으로 요청을 하고 text 변환 코드를 전달

    # 서버가 가진 클라이언트가 접속할 때 정보로 생성된 Session의 객체를 통해 값을 리턴받는다.
    prepared = req.prepare()  # 서버와 연결할 1. 준비단계

    res = s.send(prepared)  # 2. 세션을 통해 연결고리를 만든다. 데이터 변환 코드 전송

    # 결과를 리턴받고 출력한다.
    res_json = res.json()

    try:
        translate = res_json["message"]["result"]["translatedText"]
        print(str(translate))
        file_out.write(str(translate) + "\n")
    except:
        pass

file_out.close()
file.close()

 

mydata_res.txt

또 하루가 저물어 가네요
Another day is coming to an end.
그리움도 잠들 시간이죠
It's time to go to sleep.
오늘도 난 혹시나 하는 맘으로
Today, I'm just wondering.
또 그대를 기다려 봤죠
I've been waiting for you again.
오지 않을 걸 알고는 있지만
I know you're not coming.
기다림으로 행복할 수 있죠
You can be happy waiting.
혼자 하는 사랑도 나쁘지 않아요
Love alone isn't bad either.
곁에 있을 때보다 더 소중하니까
I mean more than when I'm around.
그대 떠난 시간 속에 남아
You stay in the time you left.
그 사랑도 할 수 없다면
If you can't do that love,
나는 살지 못해요
I can't live.
시간이 지나 잊혀질 거라면
If it's going to be forgotten over time,
남은 날 동안 더 사랑 할게요
I'll love you more for the rest of the day.
혼자 하는 사랑도 나쁘지 않아요
Love alone isn't bad either.
곁에 있을 때보다 더 소중하니까
I mean more than when I'm around.
그대 떠난 시간 속에 남아
You stay in the time you left.
그 사랑도 할 수 없다면
If you can't do that love,
나는 살지 못해요
I can't live.
막연한 기다림 속에 슬픔을 묻고
In a vague wait, we bury our sorrows.
가끔은 혼잣말로
Sometimes I talk to myself.
난 그대와 얘기 할 수 있죠 oh
I can talk to you. oh
혼자 하는 사랑도 나쁘지 않네요
Love alone isn't bad either.
곁에 있을 때보다 더 소중하니까
I mean more than when I'm around.
다만 내가 두려워지는 건
The only thing I'm afraid of is...
긴 시간을 견디지 못해
I can't stand a long time.
그댈 잊을까봐
I'm afraid I'll forget you.
늦기 전에 꼭 다시 돌아와요
Make sure you come back before it's too late.

 

강의목표

1. 웹의 개념을 이해하고 기술할 수 있다.

2. 웹 수집 연동을 구현할 수 있다.

 

============================================================================

데이터 분석순서
데이터 수집 -> 데이터 유형 및 속성 파악 -> 데이터 변환 -> 데이터 저장 -> 데이터 정제 -> 분석 단계

데이터 수집 기술 (웹 크롤링 기술)
html이란? Hyper Text Markup Language의 약자이고 여러개의 태그를 연결해서 모아놓은 문서

 

============================================================================

웹페이지
동적페이지 : 클라이언트가 입력한 값을 처리해주는 페이지(게시판, 방명록, 회원가입, 장바구니 등)
                 asp, aspx, php, jsp 등

정적페이지 : 클라이언트가 입력한 값을 처리할 수 없는 페이지

Web Application Server WAS = Tomcat ( +java) = jsp/servlet (\.jsp)
ex) Test\a.html
http://ip:port/Test/a.html
     Test\a.jsp
http://ip:port/Test/a.jsp

프로젝트명이 application
이걸 context로 연결 
연결해서 접속하면 session 생성 webpage 보여줌
application -> context -> session -> request -> webpage 포함관계

 

beautiful soup 모듈 : 
파이썬의 코드를 복잡하게 작성하지 않아도 편하게 웹 크롤링을 할 수 있도록 
여러 함수들을 제공하는 모듈

 

[형식]
from bs4 import BeautifulSoup

# 1. 웹에서 html 문서를 가져와서 BeautifulSoup로 파싱
from bs4 import BeautifulSoup
import urllib.request  # 웹 상의 url을 파이썬이 인식할 수 있도록 해주는 모듈


def test01():
    # 3. 게시판의 날짜와 본문을 담을 리스트 객체 생성
    list_res01 = []  # 날짜를 담는다
    list_res02 = []  # 내용을 담는다

    for i in range(1, 23):  # 게시판의 끝번호까지 반복
        url_str = '크롤링할 주소입력'
        url = urllib.request.Request(url_str)  # str형식의 주소를 url로 인식하게 함
        result = urllib.request.urlopen(url).read().decode('utf-8')  # url로 접근한 소스코드를 모두 받아 decode해서 저장
        soup = BeautifulSoup(result, "html.parser")  # 모듈을 사용해 객체 생성

        # 2. 게시판의 날짜와 본문의 내용을 가져온다.
        result01 = soup.find_all('span', class_='date')  # 모듈을 사용해 소스코드 내의 태그와 클래스로 접근
        result02 = soup.find_all('p', class_='con')

        # 3. 게시판의 날짜와 본문을 담을 리스트 객체에 append
        for i in result01:
            list_res01.append(i.get_text("  ", strip=True))

        for i in result02:
            list_res02.append(i.get_text("  ", strip=True))

    # 4. 날짜와 본문을 같이 출력
    for k, h in zip(list_res01, list_res02):
        print(k + '  ' + h)

 

============================================================================

<이미지를 크롤링하는 방법>
1. 크롬 웹브라우저 설치 - https://https://chromedriver.chromium.org/downloads

2. c:\chromedriver\chromedriver.exe - ChromeDriver 90.0.4430.24  # 크롭 웹브라우저가 있는 경로

3. c:\image  # 다운받을 경로
4. 다운받을 이미지를 키워드로 결정한다. ex) 사과, 햄버거, 자동차, 동전 등
5. selenium을 설치한다.
6. 검색엔진에서 4번 키워드로 검색했을 때 웹 크롤링 코드

 

from bs4 import BeautifulSoup
import urllib.request
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
import time  # 중간중간에 sleep을 걸어야 함


def test01():
    binary = '크롬 웹 브라우저.exe 경로'

    # 브라우저를 객체로 인스턴스화 하자
    browser = webdriver.Chrome(binary)

    # input 검색창에 키워드를 입력해서 이미지를 받아오자
    browser.get("검색할 검색엔진의 주소")

	# 검색엔진에서 검색하는 input 상자의 id, class, xpath값을 받는다.
    # elem = browser.find_element_by_class_name('gLFyf.gsfi')  # 얘는 공백을 .으로 바꿔줘야 된다. 공백이 안됨.
    elem = browser.find_element_by_xpath('//*[@id="sbtc"]/div/div[2]/input')

    # 키워드 검색어 입력
    elem.send_keys("사과")  # 크롤링하고 싶은 검색어

    # 검색어를 엔터 눌러서 검색
    elem.submit()

    # 스크롤을 내리려면 브라우저 이미지 검색결과 부분(<body></body>) 마우스를 한 번 클릭하고 End키를 눌러야 한다.
    for i in range(1):
        browser.find_element_by_xpath("//body").send_keys(Keys.END)
        time.sleep(3)  # END 키 누르고 내려가는데 시간이 걸려서 sleep 해줌, 키보드를 end키를 총 5번 누르는데 END 1번 누르고 10초 쉰다

    time.sleep(3)  # 네트워크 느릴까봐 안정성을 위해 sleep을 해줌
    html = browser.page_source  # 소스코드를 리턴받는다.
    soup = BeautifulSoup(html, "lxml")

    # 그림파일 저장
    # print(soup.find_all("img", class_="rg_i Q4LuWd"))  # 얘는 공백을 .으로 해도 안된다 공백은 공백
    return soup


# 이미지의 상세 url을 가져오는 함수
def fetch_list_url():
    params = []
    soup = test01()
    imgList = soup.find_all("img", class_="rg_i Q4LuWd")

    for img in imgList:
        try:
            params.append(img["src"])
        except KeyError:
            params.append(img["data-src"])

    return params


# 이미지의 상세 url을 파일로 저장하는 코드를 만들자
def fetch_detail_url():
    params = fetch_list_url()

    for idx, p in enumerate(params, 1):
        # 다운받을 폴더 경로 입력
        urllib.request.urlretrieve(p, "C:\\image\\" + str(idx) + "_google.jpg")


if __name__ == '__main__':
    fetch_detail_url()

'데이터과학자 - 강의 > python' 카테고리의 다른 글

210514 python - Open API  (0) 2021.05.14
210510 python - JSON  (0) 2021.05.10
210507 python - built in function, 모듈 활용  (0) 2021.05.07
210506 python - exception, decimal  (0) 2021.05.06
210503 python day-12 : file i/o  (0) 2021.05.04

강의목표

1. json 형식을 이용한 파일 입출력을 구현하고 실행할 수 있다.
2. 웹페이지 연동에 관한 구문을 확인하고 실행할 수 있다.
3. 정적페이지 연동을 이해하고 실행할 수 있다.

 

이번 수업은 내일까지 아마 이어질듯하다. java, tomcat, IDLE설치 등등...

 

============================================================================

Json(JavaScript Object Notation) : 데이터 교환용으로 설계된 경량 텍스트 기반 개방형 표준
  - JavaScript 객체표기법을 의미하고 Json공식 인터넷 미디어 타입(마인타입?)은 
    application/json이고 .json 확장자를 가진다.

  - xml은 데이터를 파싱하기 위해 메모리에 모두 올려놓고 작업을 하는데 데이터양이 많을 경우
    파싱작업에 부하가 걸리거나 파싱에 실패할 경우도 있기 때문에 Json을 사용하게 된다.

  - c, c++, java, python, perl 등을 포함한 규칙을 사용하게 된다. 

  - 브라우저 확장 프로그램 또는 웹사이트를 포함하는 javascript기반 응용프로그램을 작성할 때 사용

  - Json 형식은 네트워크 연결을 통해 구조화 된 데이터를 직렬화 및 전송하는데 사용되며
    주로 서버와 web 응용 프로그램 간에 데이터를 전송하는데 사용

  - web 서비스와 API는 공개 데이터를 제공하기 위해 Json 형식을 사용

 

============================================================================

Json 특징
  1. 텍스트 기반이라 읽고 쓰는 것이 간단함
  2. 프로그램 언어와 플랫폼에 독립적이므로 서로 다른 시스템간에 객체를 교환
  3. JS문법을 사용
  4. Json 전용 파서 기능을 웹 브라우저에 내장하고 있음
  5. 데이터포맷 xml보다 가볍고 빠름
  6. 통신 프로토콜을 실행함
  7. xml 데이터는 모두 string인 반면 Json은 타입을 가진다

 

============================================================================

json의 주요 메소드
1. dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, 
              cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
  - 객체를 dict/list로 변환해서 지정된 파일에 문자열로 저장한다.

2. dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, 
               indent=None, separators=None, default=None, sort_keys=False, **kw)
  - 객체를 dict/list로 변환해서 문자열로 리턴한다.

3. load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, 
            parse_constant=None, object_pairs_hook=None, **kw)
  - 파일에서 json형식을 로드해서 python dict/list로 읽어온다.

4. loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, 
            parse_constant=None, object_pairs_hook=None, **kw)
  - json형식을 로드해서 python dict/list로 읽어온다.

 

json.dumps, json.loads(파일 X)

import json


def test01():
    obj_json = '{"str":[42.2], "str01":42}'  # 파이썬은 문자열 만들 때 \', \" 둘 다 상관없는데 json은 key값으로 오직 \"만을 받는다.
    obj = json.loads(obj_json)

    print(obj, type(obj))

    obj = [{'a': "A", 'b': (2, 4), 'c': 3.0}]
    data_string = json.dumps(obj)

    print(data_string, type(data_string))
    
    
test01()


#result
{'str': [42.2], 'str01': 42} <class 'dict'>
[{"a": "A", "b": [2, 4], "c": 3.0}] <class 'str'>
# 7번줄에서 obj의 키 값은 '로 줬지만 json으로 dump할 때 "로 변환 됨

 

json.dump, json.load(파일 O)

import json


def test02():
    obj_json = {"str": [42.2], "str01": 42, "str02": "대한민국"}
    file_name = "data.json"

    # 파일에 쓰기
    with open(file_name, "w") as f:
        json.dump(obj_json, f)

    # 파일에서 읽어오기
    with open(file_name) as f:
        result = json.load(f)

    print(result)
    
    
test02()


#result
{'str': [42.2], 'str01': 42, 'str02': '대한민국'}

 

json.loads(json_string, object_hook=class_name)

import json

s = '{"name": 1234, "family": ["mom", "dad", "brother"], "country": "대한민국"}'


class test:  # 3. d = s
    def __init__(self, d):  # __dict__는 dict 타입을 클래스의 속성처럼 접근 가능하게 해준다.
        self.__dict__ = d


if __name__ == '__main__':
    data = json.loads(s, object_hook=test)  # object_hook은 json.load로 dict 객체를 만들고 class 만들어서 __dict__에 넣을걸 한번에 하는 작업으로 이해

    print(type(data))
    print(data.name)
    print(data.family)
    print(data.country)
    
    
#result
<class '__main__.test'>
1234
['mom', 'dad', 'brother']
대한민국

 

============================================================================

1. json 모듈로 student.json 파일을 읽어오자
2. Object_hook Student 클래스를 만들어서 데이터를 대입한다
3. 이름 : 총점으로 출력한다 ex) Ruse : 270

 

student.json

{"STUDENT" :
  [
    {"NAME" :"Dominica","SCORE" : {"KOR":10,"ENG":20,"MATH":30}},
    {"NAME" :"Dominico","SCORE" :{"KOR": 90,"ENG":40, "MATH":100}},
    {"NAME" :"RuRe","SCORE" :{"KOR": 90,"ENG":90, "MATH":90}}
  ]
}
import json


class Student:
    def __init__(self, data):
        self.__dict__ = data
        
        
def prn():
    with open("student.json") as f:
        data = json.load(f, object_hook=Student)

        for my in data.STUDENT:
            sum_score = my.SCORE.KOR + my.SCORE.ENG + my.SCORE.MATH
            print(f"{my.NAME} : {sum_score}")
            
            
prn()


#result
Dominica : 60
Dominico : 230
RuRe : 270

============================================================================

[번외 1]

MEAN stack : MongoDB, Express.js, AngularJS, Node.js

MongoDB - document database
Express(.js) - Node.js web framework
Angular(.js) - a client-side JavaScript framework
Node(.js) - the premier JavaScript web server

 

============================================================================

[번외 2]

웹 서비스(Web Service)
네트워크 상에서 서로 다른 종류의 컴퓨터들간에 상호 작용을 하기 위한 서비스 지향적
분산 컴퓨팅 기술의 일종으로 SOAP, WSDL, UDDI 등의 주요 표준 기술로 이루어진 소프트웨어 시스템

  - 웹 서비스에서 네트워크 상에서 메시징 작업을 이용해서 DATA를 전송하게 되는데 웹 상에서
    데이터를 교환하는 방법은 두 가지 형식을 많이 사용한다.

  - 문서형식 (Document -style)을 이용해서 데이터를 교환하는 xml(eXtensible Markup Language),
    dict, list 혹은 내부 정보를 프로그램으로 서로 교환할 때 사용하는 Json이 있다.

구성요소
  - SOAP : Simple Object Access Protocol
        XML과 Http 등의 프로토콜을 기본으로 하여 다른 컴퓨터에 있는 데이터나 서비스를
        호출하기 위한 통신규약
  - WSDL : Web Service Description Language
        웹 서비스에서 제공하는 기능들(서비스)을 외부에서 이용할 수 있도록 그 사용법을 알려주는
        인터페이스로 xml 기반으로 작성된다.
  - UDDI : Universal Description, Discovery and Intergration
        개방형 표준과 비독점적인 기술을 기반으로 개발된 전역 비즈니스 레지스트리를 다양한
        웹서비스를 사용자가 검색해서 사용할 수있는 요소이다.

 

============================================================================

[번외 3]

xml(eXtensible Markup Language) : 
1998년에 w3c에서 표준으로 채택한  다목적 마크업 언어로 많은 곳에서 서비스를
메시징하고 있기 때문에 사용한다. 
ex) 선진형 방재기상 정보 웹서비스, 기상예보, 기상특보 등의 정보를 제공
ex) 우편번호 API, 종추적 API, EMS 종추적 API 
ex) 개별 웹사이트 소유자 및 개발자에게 웹서비스를 할 수 있게 제공되는 무료 플랫폼 등

from _collections import defaultdict

from _collections import defaultdict


def test01():
    artist = ['비틀즈', '비틀즈', '아이유', '아이유', '마이클 잭슨', '마이클 잭슨']
    music = ['yesterday', 'imagine', '너랑나', '마시멜로우', 'beat it', 'smooth criminal']
    gini = defaultdict(list)  # 기본 dict를 만들어서 ()객체를 key로 생성하고 value를 추가로 dict로 만드는 과정

    for idx, val in enumerate(artist):
        gini[val].append(music[idx])

    return gini
    
    
a = test01()

print(a)

# =====================값 추출=====================
for i in a.values():
    print(i)
    
    
#result
defaultdict(<class 'list'>, {'비틀즈': ['yesterday', 'imagine'], '아이유': ['너랑나', '마시멜로우'], '마이클 잭슨': ['beat it', 'smooth criminal']})
['yesterday', 'imagine']
['너랑나', '마시멜로우']
['beat it', 'smooth criminal']

기존의 dict는 이미 있는 key : value를 다시 넣으면 새로운 value가 덮어쓰기 되는데

defaultdict는 value가 리스트로 업데이트가 되어 기존의 value가 사라지지 않는다.

 

============================================================================

sum(), all(), any()

def test01():
    # 1. list, tuple 객체의 요소의 합을 출력하자
    list_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    res = sum(list_data)

    print(list_data)
    print(res)
    
    
test01()


#result
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
55


def test02():  # list 요소가 bool값 (all, any)  all() : And, And....  any() : or, or....
    '''
    True = 1, False = 0
    all() : list의 모든 요소가 참인 경우에만 True를 리턴. 하나라도 거짓이 있으면 False
    any() : list의 모든 요소가 거짓인 경우에만 False를 리턴. 하나라도 거짓이 있으면 True
    '''
    list_data1 = [True, True, True]
    list_data2 = [True, False, True]

    print(all(list_data1))
    print(all(list_data2))
    print(any(list_data1))
    print(any(list_data2))
    
    
test02()


#result
True
False
True
True

============================================================================

import string, ord(char), chr(int)

import string


def test01():
    print(string.ascii_uppercase)
    
    for i in string.ascii_uppercase:
        print(f"{i} ===> {ord(i)}", end=", ")
        
    print()
    for i in string.ascii_lowercase:
        print(f"{i} ===> {ord(i)}", end=", ")
    
    print()
    for i in range(65, 91):
        print(f"{i} ===> {chr(i)}", end=", ")
        
 
test01()


#result
ABCDEFGHIJKLMNOPQRSTUVWXYZ
A ===> 65, B ===> 66,  ...  Z ===> 90,
a ===> 97, b ===> 98,  ...  z ===> 122,
65 ===> A, 66 ===> B,  ...  90 ===> Z, 

 

============================================================================

import numpy as np (맛보기)

# numpy
import numpy as np
import random


# 한 개의 주사위를 360번 던져서 3의 배수의 눈이 나오는 횟수를 구하는 것을 1000번 하고
# 1000번의 결과를 x = []라는 변수에 넣어 x에 대한 평균, 분산, 표준편차를 구하자
def test():
    dice = [1, 2, 3, 4, 5, 6]
    x = []

    for i in range(1000):  # 1000번 반복 수행
        count = 0

        for j in range(360):
            res = random.choice(dice)  # dice list 중 랜덤으로 하나의 값을 res에 저장

            if res % 3 == 0:  # 그 주사위의 눈을 3으로 나눈 나머지 값이 0이면
                count += 1      # 카운트를 1씩 증가

        x.append(count)

    print(np.mean(x))  # 평균
    print(np.var(x))     # 분산
    print(np.std(x))     # 표준편차


test()


#result 수행할 때마다 당연히 결과가 다름
120.181
75.348239
8.68033634140982

'데이터과학자 - 강의 > python' 카테고리의 다른 글

210512 python - Web crawling  (0) 2021.05.12
210510 python - JSON  (0) 2021.05.10
210506 python - exception, decimal  (0) 2021.05.06
210503 python day-12 : file i/o  (0) 2021.05.04
210503 python day-11 : os, file i/o  (0) 2021.05.03

강의목표

1. 예외처리를 할 수 있다. 
2. decimal 모듈을 사용해서 활용해 보자.

============================================================================

Exception : 특정에러에 대응하는 방법을 pvm에서 해당 특정에러에 대한 클래스를 제공한다. 
ex)
oa 프로그램에서 갑자기 병목현상이 발생할 경우 .bak 파일에 작업 내용을 자동 저장
ZeroDivisionError : 예외 클래스

Error는 크게 두 가지로 분류 : syntax Error, semantic Error
syntax Error(구문오류) : 
parsing error(파싱오류)라고도 하며 프로그램 문법에 맞지 않으면 발생하는 오류이다.
구문오류가 발생하면 오류 메시지가 표시되며 오류가 발견된 지점은 줄번호와 위치표시로 알 수 있다.

semantic Error :
프로그램 수행중에 발생할 수 있는 Error로 사전에 프로그래머가 예상해서 처리할 수 있는
가벼운 에러를 말한다. semantic Error를 Exception이라고 부른다.

 

============================================================================

Exception Handling :

예외를 방치하거나 에러로 인한 프로그램 수행 결과가 잘못 동작을 하는 것이 아니라

에러를 잡고 처리하는 방법을 제공하는 것을 말한다.

try ~ except, try ~ else, try ~finally, try ~ else ~ finally

 

[형식]
try:
    <code block>
    실행해볼 코드
except 예외종류, 예외변수:
    <예외 발생 시 실행되는 코드>
else:
    <code block>
    예외가 발생하지 않았을 때 실행되는 코드
finally:
    예외 발생 유무에 상관하지 않고 꼭 실행되는 코드

 

ex1) ZeroDivisionError

# case1 :ZeroDivisionError 발생
def excep_test01():
    try:
        r = 10 / 0
        print("이 프린트문은 에러 밑에 있으니 출력이 되지 않아")  # 윗 문장에서 에러가 발생해 except로 진입한다.
    except ZeroDivisionError:  # pvm에서 Error의 종류에 해당하는 클래스를 생성해서 리턴되는 것을 except에서 해결
        print("0으로 나누려고 시도했었다.")
    else:
        print("else")
    finally:
        print(2222222222222222)  # 파일, db등의 close(), 로그아웃
        

excep_test01()


#result
0으로 나누려고 시도했었다.
2222222222222222


# case2: ZeroDivisionError 발생X
def excep_test01():
    try:
        r = 10 / 1
        print("이 프린트문은 에러 밑에 있으니 출력이 되지 않아")
    except ZeroDivisionError:
        print("0으로 나누려고 시도했었다.")
    else:
        print("else")
    finally:
        print(2222222222222222)
        

excep_test01()


#result
이 프린트문은 에러 밑에 있으니 출력이 되지 않아
else
2222222222222222

 

ex2) IndexError

def excep_test02():
    L = [1, 2, 3]
    
    try:
        num = L[4]
    except IndexError as ie:
        print("Index Error :", ie)
        print(type(ie))
    else:
        print("keep calm and go ahead")
        
        
excep_test02()


#result
Index Error : list index out of range
<class 'IndexError'>

 

============================================================================

사용자 Exception : 
Exception class를 상속 받아서 재정의, 정의, 구현 등을 사용해서 클래스를 선언한다.
상속을 받아 구현한 사용자 정의 Exception 클래스는 
raise 키워드를 사용해서 에러를 강제로 발생시킨다.


[형식]
raise 예외 클래스

class MyException(Exception):
    def __init__(self, value):  # 4. 에러 발생해서 클래스 생성 value = err_msg = My Error!!!!!
        self.__value = value  # 5. 멤버변수 __value = My Error!!!!!

    def __str__(self):  # e를 실행하면 이 함수가 작동하나 봄
        return self.__value  # e에다가 값 리턴


def raise_exception(err_msg):  # 사용자 함수 2. err_msg = My Error!!!!!
    raise MyException(err_msg)  # 3.  에러발생시킴 err_msg = My Error!!!!!


if __name__ == '__main__':
    try:
        raise_exception("My Error!!!!!")  # 1. 함수 호출
        # = raise MyException("My Error!!!!!") 함수로 만든 이유 = 그냥
    except MyException as e:  # 6. 클래스 생성됐으니 에러 발생
        print(e)  # 7. e를 실행, # 9 print문 실행


#result
My Error!!!!!

 

============================================================================

Decimal
진법 변환 에러에 대해 정확한 값을 얻을 수 있도록 제공되는 모듈
  - 부동소수점 방식 : 소수점의 위치를 고정하지 않고 그 위치를 찾아내는 수를 따로 적는 방식
  - 유효숫자를 나타내는 가수(mantissa)와 소수점 위치를 풀이하는 지수(exponent)를 나누어서
    표현하며 [가수]*[밑수] [지수]와 같은 형태를 가진다.
>>> 1/3
       0.333333333333
  - 실제 컴퓨터에서는 보통 이진법을 이용하며 값을 먼저 이진수로 변환 후 정규화하고
    그것을 다시 정형화된 형식으로 표현한다. 
    표현식이 끝나면 결과값이 오버플로우되어 무한대 값이 되거나 언더플로우 되었을 때 
    비정상적인 값 또는 0이 될 수 있다. 만약 비정상 값이 되면 유효숫자를 잃어 버리게 된다.
>>> (90.7 + 30.2) + 0.0002
       120.90020000000001

Deciaml 특징:
  - 소수점 자리의 정밀도 조절을 할 수 있다.
  - 큰 정밀도 연산도 사용할 수 있다.
  - 실수를 정확하게 표현할 수 있다.

import decimal

if __name__ == '__main__':
    a, b = decimal.Decimal('90.7'), decimal.Decimal('30.2')
    print(a, b, a + b)
    print(type(a), type(b))
    print("========================================================================")
    c = decimal.Decimal('0.0002')
    res = (90.7 + 30.2) + 0.0002
    print(res)
    print((a + b) + c)
    print("========================================================================")
    decimal.getcontext().prec = 6
    e, f = decimal.Decimal(1), decimal.Decimal(3)
    print(1 / 3)
    print(e, f, e / f)
    print((a + b) + c)


#result
90.7 30.2 120.9
<class 'decimal.Decimal'> <class 'decimal.Decimal'>
========================================================================
120.90020000000001
120.9002
========================================================================
0.3333333333333333
1 3 0.333333
120.900

 

============================================================================

[번외1]

모듈을 import 하는 방법
1. import 모듈명
  - 일단 해당 모듈이 이미 로딩된 상태인지 확인하고 없으면 모듈명.py를 탐색한다. 

2. from 모듈명 import 컴포넌트, 컴포넌트
  - 지정된 컴퍼넌트들을 현재의 네임스페이스로 로딩

3 import 모듈명 as 별칭
  - 네임스페이스에서 충돌을 방지하거나 긴 이름에 대처하는 별칭을 지정할 때 사용

4. from 모듈명 import 컴포넌트 as 별칭
  - 네임스페이스에서 충돌을 방지하거나 긴 이름에 대처하는 별칭을 지정할 때 사용

 

============================================================================

[번외2]

class 내의 __str__ 함수는 원래 
해당 클래스를 상속받은 인스턴스를 print 할 때 나오는 주소값이 저장 되있는 함수

class Test():
    pass


a = Test()
print(a)


#result
<__main__.Test object at 0x00000192BD756FD0>

 

이걸 오버라이딩(Overriding)해서 출력함수로 사용

class Test():
    def __str__(self):
        return "출력할 내용을 정의"


a = Test()
print(a)


#result
출력할 내용을 정의

 

 

강의목표

1. 바이너리 타입 및 객체 단위 파일 입출력을 구현할 수 있다.

 

============================================================================

바이너리 타입(이진화 = stream 파일 입출력) : 
파일을 열어서 1바이트씩 데이터를 읽어서 화면에 hex 코드로 출력하는 방법

[형식]
rb, wb로 지정

모든 데이터의 이동은 stream 텍스트도 바이트로 변환해서 이동
stream : 바이트 단위로 데이터를 주고 받는 통로, 바이트 단위로 읽고 쓰는 저장소
영숫자 + 특수문자 => 1byte => stream 
                             unicode -> utf-8(2byte) -> utf-16(3byte)

with open("file_test01.txt", "wb") as f:
    # f.write(b'ABC123')  # 1byte 이내 코드값 변환 ASCII, (확장형 코드 = scan code, unicode)
    str = '대한민국 우리나라'
    f.write(bytes(str,'utf-8'))
    
    
with open("file_test01.txt", "rb") as f:
    print(str(f.read(), "utf-8"))
    # print(f.read().decode()) 도 가능
    
    
#result
'대한민국 우리나라'

seek(num), tell()

with open("test.txt", "r") as f:
    str = f.read()  # 전체 파일의 내용을 읽어서 리턴
    print(str)

    f.seek(0)  # 파일 포인터의 위치를 0으로 이동

    while 1:
        l = f.readline()  # 한줄씩 읽어서 리턴
        if l:
            print(f.tell())  # 현재 파일 포인터의 위치를 반환
            print(l, end="")
        else:
            break

    f.seek(0)  # 파일 포인터의 위치를 0으로 이동
    print(f.tell())

    ls = f.readlines()
    print(ls)  # 전체 출력
    print(ls[3][2])
    print(f.tell())

    f.seek(9)
    print(f.read())

 

============================================================================

객체단위 파일 입출력 : 지속 모듈 중의 하나로 파이썬 객체를 저장하는 모듈을 말한다.
1) DBM 관련 모듈 : anydbm, dbm, gdbm, dbhash, dumbdbm 등 시스템에 따라서 관련된 모듈
2) marshal 모듈    : 파이썬의 객체를 이진 포맷으로 저장(재귀적인 dict, list 객체 불가)
                          .pyc 파일의 컴파일된 코드를 쓰고 읽어들이는데 사용된다.
3) shelve : dict형식으로 데이터를 접근하는 dbm 모듈 중 anydbm과 동일하지만 임의 파이썬 객체가
              value로 사용할 수 있다. 내부에서 dict형 인터페이스를 위해 anydbm 모듈을 사용하고
              객체 저장을 위해 cPickle 모듈을 이용한다.

 

pickle : 파이썬에서는 개체를 파일에 저장한다는 의미를 가진다.
객체상태를 저장 -> 이진파일로 변환 저장 -> 전달 -> 복원
[장점]
  - 파이썬의 기본데이터 객체 및 사용자 클래스를 저장한다

  - 서로 참조되는 객체까지의 관계도 저장한다.

  - 재귀적인 관계도 처리된다

  - 디버깅을 설계하고 문제가 생겼을 때 텍스트 에디터로 복구를 쉽게 할 수 있다.

[단점]
  - 파일의 용량이 크다

  - 처리속도가 느리다.

cPickle : Pickle의 단점을 보완한 모듈
3.5ver 이후 윈도우 cPickle이 pickle로 병합되었다.

1. import pickle or cPickle
2. dump(object, file) 를 이용해서 파일로 객체를 출력한다.  파이썬 -> 파일로
   dumps(object) -> string 문자열로 객체를 출력한다.       파이썬 -> 파일로
3. load(file) -> object : 파일에서 객체를 리턴받는다.          파일 -> 파이썬 없으면 없는끼리
   loads(bytes) -> object : 문자열에서 객체를 리턴한다.      파일 -> 파이썬 s는 s끼리

 

튜플객체 전달

import pickle

book = {'java': 30000, 'python': 35000, 'oracle': 40000, 'jsp': 20000}
l_list = ["abcd", 90, 90.8,"대한민국", "☆★","金"]
t_tuple = (book, l_list)
print(t_tuple)

with open('ptest.txt', 'wb') as f:
    pickle.dump(t_tuple, f)  # 파일에 객체를 저장

with open("ptest.txt", "rb") as f:
    res01, res02 = pickle.load(f)  # 파일에 저장된 객체를 불러오기
    print(res01)
    print(res02)
    
    
#result
({'java': 30000, 'python': 35000, 'oracle': 40000, 'jsp': 20000}, ['abcd', 90, 90.8, '대한민국', '☆★', '金'])
{'java': 30000, 'python': 35000, 'oracle': 40000, 'jsp': 20000}
['abcd', 90, 90.8, '대한민국', '☆★', '金']

 

클래스 객체 전달

import pickle


class Address:
    def __init__(self, name, addr, tel):
        self.name = name
        self.addr = addr
        self.tel = tel

    def prn(self):
        print(f"{self.name}, {self.addr}, {self.tel}\n")


if __name__ == '__main__':
    no01 = Address("홍길동", "서울", "02-000-0000")

    with open("address.txt", "wb") as f:
        pickle.dump(no01, f)

    with open("address.txt", "rb") as f:
        res = pickle.load(f)
        res.prn()
        
        
#result
홍길동, 서울, 02-000-0000

 

============================================================================

번외

overloding 기능을 가진 메소드 : 메소드 이름은 동일한데 괄호 안 매개인자의 개수나 타입을
                                          다르게 지정해서 호출하도록 선언하는 방법

 

ex)
bytes(iterable_of_ints) -> bytes
bytes(string, encoding[, errors]) -> bytes
bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
bytes(int) -> bytes object of size given by the parameter initialized with null bytes
bytes() -> empty bytes object

강의목표

1. OS모듈의 내용을 살펴보고 운영체제의 값을 구현하는 클래스와 메소드를 활용할 수 있다.
2. 파일의 입출력을 구현할 수 있다.

 

============================================================================

OS : 운영체제와 관련된 기능을 가진 모듈

import os

print("현재 운영체제 :", os.name)
print("현재 폴더 :", os.getcwd())

# 폴더 만들기/지우기
os.mkdir("test")  # 현재 경로에서 바로 아래만. 한번에 깊게 만들려면 mkdirs()
os.rmdir("test")  # 폴더가 비어있야 제거 가능.

# 파일 이름변경/지우기. 파일이 있어야 함
os.rename("old.txt", "new.txt")
os.remove("new.txt")  # == os.unlink()

# os.path를 활용한 파일경로 및 파일이름 분할
file = 'c:\\test\\b.txt'

a = os.path.basename(file)  # 파일이름만 분할
b = os.path.split(file)     # 파일경로와 파일이름을 분할하여 튜플로 리턴
c = os.path.normpath(file)  # 리눅스, 윈도우에서 경로로 인식한다.
print(a)
print(b)
print(c)


#result
b.txt
('c:\\test', 'b.txt')
c:\test\b.txt

 

============================================================================

파일 입출력

1. byte    = 이미지, 동영상, 음성

2. 문자    = txt

3. object  = 동일한 패턴, 자주사용하는 패턴 --> Class --> 객체생성 --> 입출력

 

[형식]

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

open() --> write()/read() --> close()의 형식을 취한다.

content = "Hello Python!"

f = open("content.txt", 'w')  # 현재 디렉토리에 data.txt 파일을 쓰기전용으로 생성 후 내용 저장
f.write(content)
f.close()

f = open("content.txt", 'r')
print(f.read())
f.close()


#result
Hello Python!

 

with ~ as 문을 활용하여 close()가 자동으로 되는 파일입출력 형식

content = "Hello Python!"


with open("content.txt", 'w') as f:
    f.write(content)
    
with open("content.txt",'r') as f:
    print(f.read())
    
    
#result
Hello Python!

 

readline()은 함수가 실행될 때마다 한 줄씩 읽어온다.

readlines()는 함수가 실행되면 한 줄씩 읽어서 리스트에 넣어 리턴한다.

print("=======case1=========")
f = open("content.txt", 'r')
line = f.readline()

while line:
    print(line)
    line = f.readline()
    
f.close()


print("=======case2=========")
f = open("content.txt", 'r')

while True:
    line = f.readline()
    
    if not line:
        break
    print(line)
    
f.close()


print("=======case3=========")
f = open("content.txt", 'r')

for line in f:
    print(line, end="")
    
f.close()

강의목표

1. 다중상속에 대한 개념을 이해하고 선언할 수 있다.
2. 다형성의 개념을 이해하고 설계할 수 있다.

 

============================================================================

다중상속 : 하나 이상의 선조를 가질 수 있는 후손의 구조
두 개 이상의 선조가 같은 메소드를 가지고 있을 때 먼저 정의된 쪽이 호출된다.

class Dog:
    def sound(self):
        print("bark")


class Cat:
    def sound(self):
        print("meow")
        
        
class Chimera(Cat, Dog):  # 다중상속, SubClassing
    pass
    
    
if __name__ == '__main__':
    Chimera().sound()
    
    
#result
meow

# class Chimera(Dog, Cat): 을 하면 결과로 bark이 나온다

 

============================================================================

다형성
어떤 한 요소에 여러 개념을 넣어놓은 것으로 일반적인 클래스 상속 구조에서
재정의(상속시에 같은 이름의 메소드가 여러 클래스에서 다른 기능을 하는 것)하는 것을 의미

특징
    AA <- BB, AA <- CC
  - 여러 개의 클래스가 같은 이름의 메소드에 대하여 각자 다른 방법으로 작동할 수 있도록 설계

  - 하나의 데이터 유형(선조 객체) 변수로 여러 유형의 객체 참조(후손)가 가능하다

  - 변수가 참조하는 객체의 유형에 맞는 메소드를 자동으로 호출할 수 있다.

  - 추상화를 이용하여 다양한 구현을 제공할 수 있다.

강사님이 만드셨다니까 올려도 괜찮지 않을까...


필요조건
1. 상속관계의 클래스이면서 후손 클래스 객체에서 작동된다.
2. 후손 클래스 객체의 메소드 호출은 선조 클래스 유형의 변수를 통해 호출되며 
   재정의 된 메소드여야 한다.

from abc import abstractmethod, ABCMeta  # 추상화를 위해 모듈을 import
class Base(metaclass=ABCMeta):
    @abstractmethod                      # 메소드를 추상메소드로 지정하는 데코레이션
    def start(self):
        print("파이썬만 추상메소드에 기능을 줄 수 있다")
        print("Base start")

    @abstractmethod                      # 메소드를 추상메소드로 지정하는 데코레이션
    def Stop(self):
        print("Base Stop")

# 선조클래스에 추상메소드가 있기때문에 자손클래스들은 Subtyping을 해줘야한다
class Cat(Base):
    def start(self):
        print("Cat start")

    def Stop(self):
        print("Cat Stop")


class Duck(Base):
    def start(self):
        print("Duck start")

    def Stop(self):
        print("Duck Stop")


class Puppy(Base):
    def start(self):
        print("Puppy start")

    def Stop(self):
        print("Puppy Stop")


def MY_Call(m):
    m.start()
    m.Stop()


if __name__ == '__main__':
    MY_Call(Puppy())
    MY_Call(Cat())
    MY_Call(Duck())
    
    
#result 똑같은 함수명으로 호출했지만 생성된 객체에 따라 결과값이 전부 다양하게 형성됨
Puppy start
Puppy Stop
Cat start
Cat Stop
Duck start
Duck Stop

 

============================================================================

추상화(abstract)
  - Subclassing : 상속의 유형 중에서 선조 클래스의 속성과 구조를 그대로 가지면서
                      새로운 데이터 멤버 변수와 멤버 메소드를 추가해서 재사용하는 방법
  - Subtyping : 선조 클래스가 수행할 명령을 선언하고 후손 클래스가 상속을 받아서
                    선조 클래스의 객체를 후손 클래스의 타입으로 대처해서 실행할 수 있게 해주는 방법

# 파이썬의 서브타이핑은 추상클래스를 지원하면서 duck typing을 지원한다.
# duck typing은 동적바인딩의 한 종류로 duck클래스 객체를 선언하면 duck이 생성되어 
   호출된다는 말로 객체의 변수 및 메소드의 집합이 객체의 타입을 결정하는 것을 말한다.

서브타이핑시에 선조의 주소로 후손의 객체를 가지는 것이 아니라 추상클래스를 선언하고
재정의를 하면서 후손의 객체 주소를 각각 생성해서 메소드를 실행하게 된다.

1. 추상메소드 : 후손을 위해 선조가 강제로 재정의할 수 있게 선언된 메소드
2. 추상메소드를 포함한 클래스는 추상클래스가 된다.
3. 추상클래스는 객체 생성이 불가능하다.
4. 추상클래스를 상속받는 후손클래스가 선조의 추상메소드를 재정의하지 않으면 
   본인이 추상클래스가 된다.

 

파이썬에서 선언하는 추상클래스는? ABCMeta: Abstract Base Class Meta Class

from abc import abstractmethod, ABCMeta
@abstractmethod : 메소드를 추상메소드로 지정
@property : 메소드를 변수로 호출할 수 있도록 지정
@staticmethod : 정적메소드로 지정
@classmethod : 클래스 인스턴스 메소드로 지정

# @property : 메소드를 변수로 호출할 수 있도록 지정
class My:
    def __init__(self):
        self.x = 0

    @property  # @mFun.getter
    def mFun(self):     # 멤버 변수 x를 리턴하는 method
        return self.x

    @mFun.setter
    def mFun(self, x):  # 멤버 변수 x에게 지역변수 x가 값을 받아 전달 및 변경하는 method
        self.x = x


if __name__ == '__main__':
    a = My()
    a.mFun = 100         # mFun(100)으로 값을 전달 해야하지만 변수처럼 전달 가능
    print(a.mFun)         # mFun()으로 값을 전달 받아야하지만 변수처럼 받기 가능
    
    
#result
100

1. 파이썬의 상속구조를 이해하고 구현할 수 있다.

 

============================================================================

클래스의 상속
상속(inheritance) : 하나의 객체를 설계할 수 있는 구체(Concrete) 클래스 또는 단일 클래스를
                        기능 추가 및 변경, 특성을 추가해서 새로운 확장형 클래스를 정의하는 것

상속의 특징
  - 선조가 후손에게 재산을 상속하듯이 클래스가 또 다른 클래스에게 상속할 수 있다.

  - 클래스간의 상속은 멤버변수, 메소드를 또 다른 클래스에 그대로 전해 주며
    후손은 선조의 메소드를 후손에서 선조클래스명.멤버로 호출이 가능하다.

  - 생성자, 소멸자, __특정메소드__, private(__)는 상속받을 수 없다.

  - 상속의 목적은 재사용, 간결성, 확장성이다. 

상속의 선언방법
  - 선조클래스와 후손클래스의 상속은 다중 상속을 지원한다.

[형식]
class 클래스명(선조클래스명,,,,,):
    <<코드>>

class Person:                               #5
    def __init__(self, name, age):          #6. 선조의 객체가 생성되면서 멤버변수에 값전달
        self.name = name
        self.age = age
        
    def info(self):
        return self.name, self.age
        
        
class Student(Person):                      #2
    def __init__(self, name, age, grade):   #3
        super().__init__(name, age)         #4 선조의 생성자
        self.grade = grade                  #7 객체 생성하면서 grade 변수 값 전달

    def getInfo(self):
        return self.info(), self.grade
        
        
if __name__ == '__main__':
    x = Student("KHJ", 13, 6)   #1. Student("KHJ", 13, 6) #8 생성된 주소를 X에 대입
    print(x.getInfo())
    
#result
(('KHJ', 13), 6)


# 상속을 받으면 후손클래스를 생성할 때 항상 선조클래스가 먼저 생성된다.


재정의 : 메소드 재정의
선조 : prn() - 히든
후손 : prn()

선조 : getTot() = 2과목
후손 : getTot() = 3과목
  - 상속받은 후손 클래스에서 상속해 준 선조 클래스에 이미 정의 되어 있는
    메소드의 기능을 변경해서 새로 정의하는 것을 말한다.


  - 선조클래스에 메소드가 존재해야 재정의가 된다.


  - 선조가 가진 메소드의 파라미터 개수가 같아야 한다.


  - 리턴형은 같지 않아도 된다.

class MyScore:
    def __init__(self, kor, eng):
        self.kor = kor
        self.eng = eng

    def getTot(self):
        print("선조getTot")
        return (self.kor + self.eng)


class MyScore_sub(MyScore):
    def __init__(self, kor, eng, mat):
        super().__init__(kor, eng)
        self.mat = mat

    def getTot(self):
        print("후손getTot")
        return super().getTot() + self.mat


if __name__ == '__main__':
    print(MyScore(100, 100).getTot())
    print()
    print(MyScore_sub(100, 100, 100).getTot())
    

#result
선조getTot
200

후손getTot
선조getTot
300

강의목표

1. 클래스 생성 후 연동할 수 있다.
2. 클래스 멤버를 선언하고 생성자와 소멸자를 이해할 수 있다.
3. 클래스 선언 및 객체 생성, 멤버 호출을 실행할 수 있다.

 

============================================================================

OOP(객체 지향 프로그래밍)의 특징
  - 클래스  - 사용자 자료형 = 변수 + 메소드
    캡슐화  - 은닉된 멤버 변수에게 오픈된 메소드가 값을 전달 및 변경하는 구조


  - 상속     - 클래스의 기능을 확장, 선조 클래스가 1이면 단일상속, 1more(+)면 다중상속

    자손 클래스(this class) -----------> 선조 클래스(super class)
    선조가 가지고 있는 기능(메서드)이 자손에게 상속되면서 확장
    선조는 자손을 모르지만 자손은 선조를 알고 상속받는다
    # this : 현재 object를 지칭하는 연산자. python은 self


  - 다형성  - 다양한 형태의 성질로 이루어진 클래스의 동적 바인딩 구조

    다형성 = 추상화, 동적바인딩
    메소드 이름은 같은데 기능은 조금씩 다름, 리턴이 다름
    선조클래스는 자손들의 틀만 잡아준다 => 추상화

 

============================================================================

자료형선언 -> 객체 생성 -> 멤버 호출
[형식]
class 클래스이름 (상속 클래스명):
    <클래스 변수 선언>
def 클래스 함수(self, ...): -> 클래스 내부에 선언되는 매개인자는 첫번째 자리에 self
    <수행할 문장>

ex)
값을 받아서 저장하고 추가하는 클래스를 만들려고 한다.
값을 받아 저장하는 멤버를 가진 메소드를 empty()라고 하고 
값을 받아 추가하는 메소드를 add()라고 명명하게 설계하자
[step 01 자료형, 클래스 선언]

class Test:
    def empty(self):
        self.data = []
        
    def add(self, x):
        self.data.append(x)

 

[step 02 객체 생성]
Test클래스가 선언 및 정의가 되면 클래스 객체 생성을 통한 인스턴스를 만든다.
클래스변수 = 클래스명() # 생성자를 호출하면서 객체를 생성

class Test:
    def empty(self):
        self.data = []
        
    def add(self, x):
        self.data.append(x)
        
        
my01 = Test()
my02 = Test()

 

[step 03 멤버 호출]

class Test:          # object의 자손클래스가 되어 선조의 메소드들을 참조하고 있다. class Test(object):
    def empty(self):
        self.data = []
        
    def add(self, x):
        self.data.append(x)
        
        
my01 = Test()        # my01의 변수에 Test라는 클래스의 객체를 생성하게 되면 메모리에 Test클래스와 같은 자료형이
my02 = Test()        # 생성되어 메모리에 확보되고 확보된 주소가 my01 = 연산자를 통해 대입되어 참조된다.


my01.empty()
my02.empyt()

 

============================================================================

메소드에 지정하는 self의 의미
  - 클래스 내부에 선언하는 메소드의 매개인자는 첫번째 자리에 반드시 self
  - 모든 메소드는 최소한 self는 반드시 명시되어야하며 리턴되거나 매개인자로 대입받을 수 없다.
  - 객체를 통해서 호출되는 메소드의 self는 자동으로 객체 참조될 주소로 대입받는다.
  - self를 통해서 클래스의 멤버변수 or 메소드를 자유롭게 클래스 내부에서 호출할 수 있다.

 

============================================================================

클래스의 내장함수
  - 파이썬에서 사용되는 모든 클래스안에서 사용할 수 있는 특별한 메소드를 말한다.
  - 클래스의 내장함수는 크게 (생성자, 소멸자), 연산자 오버로드, 기본 자료형중 시퀀스자료형에서
    사용되는 인덱싱 관련함수 등의 세가지로 나뉜다.

생성자 : __init__(initialization) 객체가 인스턴스화 될 때 호출도는 특수 메소드
소멸자 : __del__(destructor) 인스턴스가 소멸될 때 호출되는 특수 메소드

# 생성자를 명시하지 않으면 자동으로 내부호출되어 생성되고 명시하게 되면 명시된 생성자가 호출된다.
# 생성자는 단 한번 객체를 생성할 때 자동 호출되며 해당클래스의 모든 멤버를 동적 할당 메모리로 로드하게 된다.
# 생성자의 목적은 멤버변수 초기화에 있다.
class MyDel:
    def __init__(self):  # 생성자
        print("__init__")

    def __del__(self):   # 소멸자 객체가 소멸되는 시점에서 호출되면서 리소스 해제
        print("__del__")


if __name__ == '__main__':
    a1 = MyDel()         # MyDel이라는 클래스를 생성자를 호출하면서 객체를 생성한다.
    
    
#result
__init__
__del__

 

============================================================================

번외

oop에서 접근제한자
private   - 비공개
protected  - 상속시 공개
public   - 공개
default   - 현재 패키지에서만 공개

ex)
class Test{
private int a // 비공개
}
Test t1 = new Test() -> t1.a 호출 불가능

파이썬은 표현이 다르다

__ : non-public, 기본은 public

# 정수형 변수 a를 관리하는 클래스를 만들어보자. 단, 캡슐화로 구현해보자.
# 캡슐화 : 은닉된 멤버 변수에 오픈된 메소드로 값을 전달(setXX) 및 변경하는 구조(getXX-return)
# 은닉된 멤버 변수에게 setXX으로 값 전달 및 변경하고 getXX return메소드로 리턴하는 구조
class Test():
    __a = 0  # 주소 히든 private

    def setA(self, a):   # 객체 생성 후 값을 a로 전달받아 멤버 __a에게 값 전달 및 변경
        self.__a = a  

    def getA(self):      # 객체 생성 후 a의 값을 요청받으면 return해서 알려줌
        return self.__a


if __name__ == '__main__':
    t1 = Test()
    print(t1.getA())
    t1.setA(100)
    print(t1.getA())


#result
0
100

 

+ Recent posts