ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 02-4. 클래스와 예외처리
    파이썬 2023. 8. 28. 15:05

    summary

    - function
    * docstring
    * scope : 전역, 지역 : global
    * inner function : 함수 안에 함수를 선언
    * lambda function : 간략한 함수를 한 줄의 코드로 작성
    * decorator : 특정 기능을 데코레이터 함수로 만들어 함수에 특정 기능을 적용하는 방법


    1.Class : 클래스

    - 변수와 함수를 묶어 놓은 개념
    - 클래스 선언
    * 변수와 함수를 클래스 안에서 선언
    - 클래스를 객체로 만들어서 클래스 안에 선언된 변수와 함수를 사용

    1.1.기본 클래스

    1.1.1.클래스 선언

    class Account:
    
      loan = 0
      deposit = 0
    
      def save(self, money):
        self.deposit += money
        print("현재 계좌 잔액 :{}원".format(self.deposit))
    
      def withdraw(self, money):
        self.deposit -= money
        print("인출 금액은 {}원. 현재 계좌 잔액은 {}원".format(money, self.deposit))
    
      def debt(self, d_money):
        self.deposit += d_money
        self.credit_debt = d_money + self.loan
        return -int(self.credit_debt)
    acc = Account()
    acc

    -><__main__.Account at 0x7fe4c1d78f10>

    acc.loan

    ->0

    1.1.2.객체지향

    - 실제 세계를 코드에 반영해서 개발하는 방법
    - 여러 명의 개발자가 코드를 효율적으로 작성해서 프로젝트를 완성시키기 위한 방법
    - 설계도 작성(class) -> 실제 물건(object)
    - 사용자 정의 데이터 타입

    acc2 = Account()
    acc2.loan = 100_000    # _는 쉼표와 같은 역할(없어도 됨)
    acc2.loan

    ->100000

    acc2.debt(50_000)

    ->-150000

    acc2.deposit

    ->50000

    1.1.3.생성자

    - 클래스의 인스턴스 객체가 생성될 때 자동으로 호출되는 메소드
    - 변수(재료)를 추가할 때 사용됨

    class Account:
    
      def __init__(self):   # 웬만하면 생성자를 넣어서 실행하
        self.loan = 0
        self.deposit = 0
        print("개설 완료")
    
      def save(self, money):
        self.deposit += money
        print("현재 계좌 잔액 :{}원".format(self.deposit))
    
      def withdraw(self, money):
        self.deposit -= money
        print("인출 금액은 {}원. 현재 계좌 잔액은 {}원".format(money, self.deposit))
    
      def debt(self, d_money):
        self.deposit += d_money
        self.credit_debt = d_money + self.loan
        return -int(self.credit_debt)
    acc3 = Account()

    ->개설 완료

    acc3.loan

    ->0

    acc3.deposit

    ->0

    acc3.loan = 500_000
    acc3.loan

    ->500000

    acc3.debt(500_000)

    ->-1000000

    1.1.4.소멸자

    - 객체가 사라질 때 자동으로 호출되는 함수

    class Account:
    
      def __init__(self):   # 웬만하면 생성자를 넣어서 실행하
        self.loan = 0
        self.deposit = 0
        print("개설 완료")
    
      def save(self, money):
        self.deposit += money
        print("현재 계좌 잔액 :{}원".format(self.deposit))
    
      def withdraw(self, money):
        self.deposit -= money
        print("인출 금액은 {}원. 현재 계좌 잔액은 {}원".format(money, self.deposit))
    
      def debt(self, d_money):
        self.deposit += d_money
        self.credit_debt = d_money + self.loan
        return -int(self.credit_debt)
    
      def __del__(self):
        print("계좌 해지 완료!")
    acc4 = Account()

    ->개설 완료

    del acc4

    ->계좌 해지 완료!

    acc4

    ->『NameError: name 'acc4' is not defined』


    1.2.상속

    - 클래스의 기능을 가져다가 기능을 수정하거나 추가할 때 사용하는 방법
    - 클래스가 가지고 있는 멤버나 메소드를 상속받는 클래스가 모두 사용
    - 상속을 해주는 클래스 : 부모 클래스 또는 슈퍼 클래스
    - 상속을 받는 클래스 : 자식 클래스 또는 서브 클래스

    1.2.1.부모 클래스(슈퍼 클래스)로 상속받기

    class Account:
    
      def __init__(self):   # 웬만하면 생성자를 넣어서 실행하
        self.loan = 0
        self.deposit = 0
        print("개설 완료")
    
      def save(self, money):
        self.deposit += money
        print("현재 계좌 잔액 :{}원".format(self.deposit))
    
      def withdraw(self, money):
        self.deposit -= money
        print("인출 금액은 {}원. 현재 계좌 잔액은 {}원".format(money, self.deposit))
    
      def debt(self, d_money):
        self.deposit += d_money
        self.credit_debt = d_money + self.loan
        return -int(self.credit_debt)
    
      def __del__(self):
        print("계좌 해지 완료!")
    class Stock(Account): # 자식 클래스 이름(상속받을 주체)
      pass  # 나중에 채워 넣기 위해 사용하는 오류 방지 구문
    stock = Stock()

    ->개설 완료

    1.2.2.overriding

    - 부모로부터 상속받은 클래스의 기능들을 수정하거나 대체

    class Stock(Account):
      def stock_trade(self, buy, sell):
        self.deposit -= buy
        self.deposit +=sell
        if buy and not sell:
          print("매수 금액 {}원. 현재 계좌 잔액 {}원".format(buy, self.deposit))
        else:
          print("매도 금액 {}원. 현재 계좌 잔액 {}원".format(sell, self.deposit))
    stock = Stock()

    ->개설 완료

    stock.stock_trade(100_000,0)

    ->매수 금액 100000원. 현재 계좌 잔액 -100000원

    stock.save(500_000)

    ->현재 계좌 잔액 :400000원

    class Employee:
      mileage = 0
      rate = round(1/15, 2)  # 1/15를 소수점 2번째자리로 반올림
    
      def __init__(self, first, last, salary):
        print("!!입사 축하!!")
        self.first = first
        self.last = last
        self.salary = salary
        self.id = first.lower() + last.lower() + "@deepnoid.com"
        self.mileage = 100_000
    
      def save_mileage(self, point):
        self.mileage += int(point) + self.salary * self.rate
        print("추가 포인트 : {}점, 누적 마일리지 {}점".format(point, self.mileage))
    emp = Employee("gildong", "hong", 1_000)

    ->!!입사 축하!!

    emp.save_mileage(10_000)

    ->추가 포인트 : 10000점, 누적 마일리지 110070.0점

    emp.rate

    ->0.07

    class Employee:
      mileage = 0
      rate = round(1/15, 2)  # 1/15를 소수점 2번째자리로 반올림
    
      def __init__(self, first, last, salary):
        print("!!입사 축하!!")
        self.first = first
        self.last = last
        self.salary = salary
        self.id = first.lower() + last.lower() + "@deepnoid.com"
        self.mileage = 100_000
    
      def save_mileage(self, point):
        self.mileage += int(point) + self.salary * self.rate
        print("추가 포인트 : {}점, 누적 마일리지 {}점".format(point, self.mileage))
    emp2 = Employee("yeounghee", "kim", 1_000)

    ->!!입사 축하!!

    emp2.rate

    ->0.07

    emp2.rate = 0.7
    emp2.save_mileage(10_000)

    ->추가 포인트 : 10000점, 누적 마일리지 110700.0점

    class Employee:
      mileage = 0
      rate = round(1/15, 2)  # 1/15를 소수점 2번째자리로 반올림
    
      def __init__(self, first, last, salary):
        print("!!입사 축하!!")
        self.first = first
        self.last = last
        self.salary = salary
        self.id = first.lower() + last.lower() + "@deepnoid.com"
        self.mileage = 100_000
    
      def save_mileage(self, point):
        self.mileage += int(point) + self.salary * Employee.rate
        print("추가 포인트 : {}점, 누적 마일리지 {}점".format(point, self.mileage))
    em3 = Employee("sara", "L", 1_000)

    ->!!입사 축하!!

    em3.rate

    ->0.07

    em3.rate = 0.7
    em3.rate

    ->0.7

    em3.save_mileage(10_000)  # Employee.rate엔 변함이 없다

    ->추가 포인트 : 10000점, 누적 마일리지 110070.0점

    1.2.3.mangling

    - 클래스 변수 안에 접근할 수 없도록 설정하는 방법
    - 변수명 앞에 __를 붙여서 사용

    class Employee:
      mileage = 0
      rate = round(1/15, 2)  # 1/15를 소수점 2번째자리로 반올림
    
      def __init__(self, first, last, salary):
        print("!!입사 축하!!")
        self.first = first
        self.last = last
        self.salary = salary
        self.id = first.lower() + last.lower() + "@deepnoid.com"
        self.mileage = 100_000
        self.__rate = round(1/15,2)
    
      def save_mileage(self, point):
        self.mileage += int(point) + self.salary * self.__rate
        print("추가 포인트 : {}점, 누적 마일리지 {}점".format(point, self.mileage))
    emp4 = Employee("data", "L", 1_000)

    ->!!입사 축하!!

    emp4.rate

    ->0.07

    emp4.save_mileage(10_000)

    ->추가 포인트 : 10000점, 누적 마일리지 110070.0점

    emp4.__rate = 0.7
    emp4.__rate

    ->0.7

    emp4.save_mileage(10_000)    # Employee.rate가 사실상 의미 없음

    ->추가 포인트 : 10000점, 누적 마일리지 130210.0점


    1.3.super()

    - 부모 클래스에서 사용된 함수의 코드를 받아서 자식(서브) 클래스의 함수에서 재사용할 때 사용

    class A:
      def plus(self):
          code1
    
    class B(A):
      def minus(self):
          code1 # super().plus()
          code2
    class Phone:
      def __init__(self, function=None):
        self.name = function
        print("{} phone 구매 완료".format(self.name))
      def calling(self):
        print("calling")
    class CameraPhone(Phone):
      def __init__(self, function=None):
        super().__init__(function)
    
      def camera(self):
        print("camera select")
    ph = Phone()

    ->None phone 구매 완료

    ph.calling()

    ->calling

    cam = CameraPhone("Camera")

    ->Camera phone 구매 완료

    cam.camera()

    ->camera select

    class WebPhone(CameraPhone):
      def __init__(self, function=None):
        super().__init__(function)
      def web(self):
        print("web browser select")
    web = WebPhone("web")

    ->web phone 구매 완료

    web.web()

    ->web browser select


    1.4.class 다중 상속

    class Plus:
      def plu(self, a,b):
        return a+b
    
    class Sub:
      def sub(self, a,b):
        return a-b
    class Calc(Plus, Sub):  # 겹치는 변수나 코드가 있을 경우,
      pass                  # 변경이 될 수 있기 때문에 왼쪽에 있는 클래스가 최상위 슈퍼 클래스가 됨
                            # 순서 중요!
    calc=Calc()
    calc.sub(1,2)

    ->-1

    calc.plu(1,2)

    ->3


    1.5.class의 getter, setter

    - 객체의 내부 변수에 접근할 때 특정 로직을 거쳐서 접근시키는 방법
    - 제약조건을 만들어서 접근 가능 여부를 만들 때 사용

    class User:
      def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name
    
      def setter(self, first_name):   # 클래스 객체 내에 들어갈 때, 변경/생성을 하려면 무조건 이 메소드를 거치게 만듦
        if len(first_name) >= 1:
          self.first_name = first_name
        else:
          print("error")
    
      def getter(self):
         print("getter")
         return self.first_name[0].upper() + self.first_name[1:].lower()
    
      name = property(getter, setter)
    user1 = User("andy", "Lee")
    user1.name

    ->getter
    'Andy'

    user1.name = "john"
    user1.name=""

    ->error

    user1.name

    ->getter
    'John'


    1.6.is a & has a

    - 클래스를 선언하는 방법
    - A is a B
    * A는 B이다. 상속을 이용해서 클래스를 만드는 방법
    - A has a B
    * A는 B를 가진다. A가 B객체를 가지고 클래스를 만드는 방법

    # is a
    class Person:
      def __init__(self, name, email):
        self.name = name
        self.email = email
    
    class UserInfo(Person):
      def info(self):
        print(self.name, self.email)
    user = UserInfo("andy", "andy@gmail.com")
    user.info()   # 상속을 받으면 상속자도 상속하는 것을 알고 있다

    ->andy andy@gmail.com

    # has a
    class Name:
      def __init__(self, name):
        self.name_str = name
    class Email:
      def __init__(self, email):
        self.email_str = email
    class User:
      def __init__(self, name_obj, email_obj):
        self.name = name_obj
        self.email = email_obj
      def info(self):
        print(name.name_str, email.email_str)
    name = Name("andy")
    email = Email("andy@gmail.com")
    user2 = User(name, email)
    user2.info()

    ->andy andy@gmail.com


    2.예외처리

    - 코드를 실행 중에 에러가 발생한 경우 에러를 처리하는 방법
    - 예외 상황이 발생하면 코드 진행이 중단되므로 계속 진행할 수 있도록 선언

    2.1.try exception

    try:
        문제가 없을 시 실행할 코드
    except:
        문제 발생(예외상황) 시 실행할 코드
    def divide():
      a,b = tuple(input("Insert Numbers : ").split(" "))
      return int(a)/int(b)
    divide()

    ->Insert Numbers : 10 0

    오류 위치

    『ZeroDivisionError: division by zero』

    print("Start")
    divide()
    print("Done")

    ->Start
    Insert Numbers : 10 0

    오류 위치

    『ZeroDivisionError: division by zero』

    def divide2():
      a,b = tuple(input("insert numbers : ").split(" "))
      try:
        return int(a)/int(b)
      except:
        print("나눗셈 실행 불가")
    print("Start")
    divide2()
    print("Done")

    ->Start
    insert numbers : 10 0
    나눗셈 실행 불가
    Done

    2.2.try except else

    - except가 실행되지 않으면 else의 실행문이 마지막에 출력

    print("start")
    num = input("set range")
    try:
      res = sum(range(int(num)+1))
    except:
      print("잘못 입력하셨습니다^^")
    else:
      print("result:", res)
    print("Done!")

    ->start
    set range : 10
    result: 55
    Done!

    print("start")
    num = input("set range")
    try:
      res = sum(range(int(num)+1))
    except:
      print("잘못 입력하셨습니다^^")
    else:
      print("result:", res)
    print("Done!")

    ->tart
    set range : 십
    잘못 입력하셨습니다^^
    Done!

    2.3.try except finally

    - except 발생 유무와 상관없이 finally 구문은 실행

    def divide():
      a,b = tuple(input("insert numbers : ").split(" "))
      try:
        return int(a)/int(b)
      except:
        print("연산 수행 불가")
      finally:
        print("연산 종료")
    print("Start")
    divide()

    ->Start
    insert numbers : 10 5
    연산 종료
    2.0

    def divide():
      a,b = tuple(input("insert numbers : ").split(" "))
      try:
        return int(a)/int(b)
      except ZeroDivisionError:
        return "0으로는 나눌 수 없습니다"
    divide()

    ->insert numbers : 10 0
    '0으로는 나눌 수 없습니다'

    2.5.설정되어 있는 Exception 오류만 출력

    try:
      print(AI)
    except Exception as e:    # Exception 내용만 가져옴(비추천) -> else 사용하는거 추천
      print(e)

    ->name 'AI' is not defined

    AI

    ->『NameError: name 'AI' is not defined』


    2.6.사용자 정의 예외처리

    - python은 정상으로 인식할 수 있으나 코드를 작성하는 작성자 기준에서 오류라고 판단되는 부분을 예외처리

    class LowNumber(Exception):
      def __str__(self):
        return "Number greater than 10"
    def input_number(num):
      if num<=10:
        raise LowNumber()   # raise : LowNumber로 설정한 예외를 발생시킴
      print(num)
    input_number(8)

    ->

    (오류 위치)

    『LowNumber: Number greater than 10』


    Magic(Special) Method

    - compare
    * __eq__: ==
    * __ne__: !=
    * __lt__: <
    - calculate
    * __add__: +
    * __sub__: -
    - __repr__: 객체의 내용을 출력(개발자용)
    - __str__: 객체의 내용을 출력

    "test" == "test"

    ->True

    "test".__eq__("test")

    ->True

    (1).__add__(2)

    ->3

    class Txt:
      def __init__(self, txt):
        self.txt = txt
    
      def __eq__(self,txt_obj):
        return self.txt.lower() == txt_obj.txt.lower()
    
      def __repr__(self):
        return "Txt(txt={})".format(self.txt)
    
      def __str__(self):
        return self.txt
    t1 = Txt("python")
    t2 = Txt("Python")
    t3 = t1
    t1 == t2, t1 == t3, t2 == t3

    ->(True, True, True)

    t1

    ->Txt(txt=python)

    print(t1)

    ->python


    후반에 많이 사용할 것이기 때문에 연습 많이 하자

    '파이썬' 카테고리의 다른 글

    02-3. 함수  (0) 2023.08.27
    02-2.조건문과 반복문  (0) 2023.08.27
    02-1. 파이썬 기초  (0) 2023.08.21
Designed by Tistory.