Quiet Time



ㅁ■ 객체와 클래스 (가장 중요한 단원) 

  • 9장 목차
  1. 객체와 클래스
  2. 클래스의 정의
  3. __init__() 메소드를 이용한 초기화작ㅇ업
  4. self에 대한 이해 
  5. 정적 메소드와 클래스 메소드 
  6. 클래스 내부에게만 ㅇ려려있는 프라이빗 멤버
  7. 상속
  8. 오버라이딩
  9. __call()__ 메소드 
  10. for문으로 순회를 할 히 있는 객체 만들기 
  11. 추상기반 클래스 
■ 9.1 객체와 클래스
객체(object) = 속성(attribute) + 기능 
    자동차          ↑            ↑
               자동차 색깔  전진, 후진,좌회전,우회전
               바퀴의 크기

코드로 구현을 하면 ? 

객체      =      변수      +      함수 

예제 :
class Car
     def __init__(self):
          self.color =0xFF0000 # 자동차의 색
          self.whell_size = 16
          self.displacement = 2000 # 엔진 배기량 


     def forward(self) : # 전진하는 기능
          pass
     def backward(self) : # 후진하는 기능
          pass
     def turn_right(self): # 우회전 하는 기능 
          pass

     def turn_left(self): #좌회전 하는 기능
          pass

if __name__ == '__main__' : # 메인 모듈일때만 아래의 스크립트를 실행해라

     my_car = Car() # 클래스를 가지고 인스턴스화 하는 코드
                    # Car() 클래스로 my_car라는 객체를 생성했다. 

     print('0x{:02X}'.format(my_car.color))
     print(my_car.whell_size))
     print(my_car.displacement)

     my_car.forward()                    # my_car 의 메소드(기능) 를 호출 
     my_car.backward()
     my_car.turn_left()
     my_car.turn_right()

■ 9.2. 클래스의 정의 


     클래스(자료형) ----> 객체(변수) 

     위의 클래스는 자료형이고 아직 객체가 되지 않았다
                    붕어빵 틀     붕어빵 (인스턴스, 실체라고 얘기함) 
                    (속성: 붕어빵 색
                           붕어빵 앙금(팥, 슈크림)

                     기능: 왼쪽으로 가라 오른쪽으로 가라 
     my_car = Car()           # Car() 클래스에 의해서 my_car라는 객체가 생성됨 인스턴스화 됨


객체 = 속성 + 기능 
      (변수)  (함수)
 
  • 코드 설명 :
     
    def __init__(self): 

1. __init__ ? 객체가 생성될때 호출되는 메소드로서 객체의 초기화를 담당한다
2.self      ? 메소드의 첫번째 매개변수로 객체 자신임을 나타냄 
3.my_car = Car() ? car() 생성자는 car 클래스의 인스턴스를 생성하여 반환한다. 
   ↑         
 인스턴스    생성자
   (실체)    (설계도)


■ 9.3 __init__() 메소드를 이용한 초기화 

클래스의 생성자가 호출이되면 내부적으로 두개의 메소드가 호출된다.
  1. __new__()   : 클래스의 인스턴스를 만드는 역할 ( 내부적으로 자동으로 호출된다.)
  2. __init__()  : 객체가 생성될  대 객체를 초기화하는 역할 
  • 만약 __init__() 메소드를 클래스 생성할 때 지정안하며 ㄴ어떻게 되는지 테스트 

1.__init__() 메소드를 지정 안 했을때

class ClassVar:
     text_list = [] # 클래스의 정의 싷점에서 바로 메모리에 할당됨 
     
     def add(self,text):
          self.text_list.append(text) 

     def print_list(self):
          print(self.text_list)

if __name__ == '__main__':
     a = ClassVar()

ㅁ■ 객체와 클래스 (가장 중요한 단원) 

  • 9장 목차
  1. 객체와 클래스
  2. 클래스의 정의
  3. __init__() 메소드를 이용한 초기화작ㅇ업
  4. self에 대한 이해 
  5. 정적 메소드와 클래스 메소드 
  6. 클래스 내부에게만 ㅇ려려있는 프라이빗 멤버
  7. 상속
  8. 오버라이딩
  9. __call()__ 메소드 
  10. for문으로 순회를 할 히 있는 객체 만들기 
  11. 추상기반 클래스 


9.4 self 에 대한 이해 
" 클래스에서 사용하는 최도 매개변수인데 self는 자기 자신을 가리킨다"

9.5 정적 메소드와 클래스 메소드 
1.인스턴스 메소드   : 로봇의 팔이 잘 작동하는지 로봇을 만들어노혹 작동해 보면 확이하는 메소드
2.클래스(정적) 메소드 : 로봇의 팔이 잘 작동하느니즈이 확인을 로봇을 만들지 않고 어떻게 하면 로봇팔이 움진인다는                     프로그램 코드를 실행히셬 확인하는 메소드 



class Calculator:
    @staticmethod
    def plus(a, b):
        return a+b

    @staticmethod
    def minus(a, b):
        return a-b

    @staticmethod
    def multiply(a, b):
        return a*b

    @staticmethod        
    def divide(a, b):
        return a/b
        
if __name__ == '__main__':        
    print("{0} + {1} = {2}".format(7, 4, Calculator.plus(7, 4)))
    print("{0} - {1} = {2}".format(7, 4, Calculator.minus(7, 4)))
    print("{0} * {1} = {2}".format(7, 4, Calculator.multiply(7, 4)))
    print("{0} / {1} = {2}".format(7, 4, Calculator.divide(7, 4)))



■ 어제 배웠던 내용 복습

   1. 클래스 와 객체
   (붕어빵틀)  (붕어빵)

      객체의 구성요소 2가지
      1. 속성(변수)
      2. 기능(함수)



   class gorilla   class pingpong
   속성: 고릴라 색깔   공과 판의 색깔, 위치
   기능: 고릴라 기능   좌로 이동, 우로 이동
   gorilla() = gorilla() -----> 생성자   pingpoing = pingpoing()

   2. 객체를 초기화 해주기 위해서 필요한 키워드, 메소드?

         self, __init__


■ 9.6 클래스 내부에게만 열려있는 프라이빗 멤버(pg200)

* 파이썬에서 사용하는 멤버 2가지

   1. public member : 클래스 안에서든 밖에서든 접근 가능 한 멤버

     예: 접두사가 두개의 밑줄이고 접미사도 두개의 밑줄이면
   __number__

   2. private member : 클래스 안에서만 접근 가능한 멤버
            클래스의 사생활을 지켜줘야할 때 요긴하게 사용됨

     예: 접두사가 두개의 밑줄이고 접미사는 없거나 하나의 밑줄

   __number
   __number_



6. 클래스 내부에게만 열려있는 프라이빗 멤버
      ○ 파이썬에서 사용하는 멤버 2가지
         i. public member - 클래스 안에서든 밖에서든 접근 가능한 멤버
            □ 접두사가 두개의 밑줄이고 접미사도 두개의 밑줄이면 퍼블릭 멤버, __number__

         ii. private member - 클래스 안에서만 접근 가능한 멤버, 클래스의 사생활을 지켜줘야할 때 요긴함
            □ 접두사가 두개의 밑줄이고 접미사는 없거나 하나의 밑줄, __number_ / __number

   • 예제 - 퍼블릭 멤버로 사용했을 경우

           class yourclass:
               pass

           class myclass:
               def __init__(self):
                   self.message = "Hello"

               def some_method(self):
                   print(self.message)

           obj = myclass()
           obj.some_method()  #메소드를 실행했기 때문에 출력이 된 것, 객체명.기능 --> 실행
           print(obj.message)  #따로 message라는 변수의 내용을 출력, print해서 본 것


   • 예제 - 프라이빗 멤버로 사용했을 경우

           class yourclass:
               pass

           class myclass:
               def __init__(self):
                   self.message = "Hello"
                   self.__private = "private"

               def some_method(self):
                   print(self.message)
                   print(self.__private)

           obj = myclass()
           obj.some_method()
           print(obj.message)
           print(obj.__private)  #프라이빗이라서 에러가 난다.

9.7 상속

   • 상속 : 클래스들끼리 유산(기능) 을 물려주는 것
      클래스  ---------------------------------> 클래스
      부모                  유산(기능)                자식  으로 물려주는 것

   • 상속을 받게 되면 자식 클래스에 부모 기능을 코딩하지 않아도 됨.
      학습시키는 클래스(짝꿍) --------------------------> 나는 핑퐁게임 클래스만 만들고 나머지는 상속 받아서 사용

   • 예제1
      class father :
def base_method(self) :


클래스 부모 ------------------- 클래스 자식 상속

상속을 받게되면 부모의 기능을 굳이 자식 클래스에 코딩하지 않아도 된다.


학습 시키는 클래스 (짝꿍) -------------------------> 나는 핑퐁게임 클래스 
                          머신러닝 기능 유산

예제 1 : 

class father 
     def base_mothod(self) :
          print("hello")

class child(father):
     pass

father = father()

father.base_method()

child = child() 
child.base_method()


예제2. __init__ 메소드를 가지고 실행하는데 부모와는 틀리게 자식에message라는 속성이 없어서 상속을 시키고 싶을때?


class father:
     def __init__(self):
          print("hello~~")
          self.message="Good Morning"

class child(father):
     def __init__(self):
          print("hello~~ I am child")

child = child()
print(child.message) <==========애기는 굿모닝 못하네여





class father:
     def __init__(self):
          print("hello~~")
          self.message="Good Morning"

class child(father):
     def __init__(self):
          father.__init__(self) # 파이썬은 암묵적인 것을 싫어하고 명시적인것을 좋아한다.
          프로그래머가 명시적으로 클래스의 초기화 메소드를 호출해주길 원함
          print("hello~~ I am child")

child = child()
print(child.message)

■ super()

child = child() 
print(child.message)

super() 는 부모클래스의 객체 역할을 하는 내장 함수.
사실상 super() 함수의 반환값을 상위객체로 지정한다 다른 클래스로 교체되거나 수정되어도 파생클래스가
받는 영향을 최소화 할 수 있다. 

class father:
     def __init__(self):
          print("hello~~")
          self.message="Good Morning"

class child(father):
     def __init__(self):
          #father.__init__(self)
          super.__init__()

          print("hello~~ I am child")

child = child()
print(child.message)

■ 다중상속

다중 상속이란 두개 이상의 클래스를 상속 받는것을 말한다
이 경우에는 두 클래스의 모든 속성을 물려받게된다
이는 하나의 자식 클래스가 두개 이상의 부모 클래스를 가지는 것이라고 할 수 있다. 


          father1            father2
               ↘              ↙
                    child
예제 1:

class father1:
     def func(self):
          print("지식")

class father2:
     def func(self):
          print("지혜")

class child(father1,father2):
     def childfunc(self):
father1.func(self)
father2.func(self)

objectchild = child()
objectchild.childfunc()
objectchild.func() # 결과 : 지식 (물려 받은 순서 우선순위 출력 father1 의 지식이 출력된다.)

■ 그런데 둘다 출력하기 싫고 하나만 출력하고 싶어서 

                 grandfather 

                          

          father1            father2

                ↘           ↙

                 grandchild



예제 : 
class grandfather:
     def __init__ (self):
          print("튼튼한 두팔")

class father1(grandfather):
     def __init__ (self):
          grandfather.__init__(self)
          print("지식")

class father1(grandfather):
     def __init__ (self):
          grandfather.__init__(self)
          print("지혜")

class grandchild(father1, father2):
     def __init__(self):
          father1.__init__(self)
          father2.__init__(self)
          print("난 행복해")

grandchild = grandchild()
결과 :
튼튼한 두팔
지식
튼튼한 두팔
지혜
난 행복해

다이아몬드 상속을 받았더니 그만 팔이 4개가 되어부럿당!

문제166. (점심시간 문제) 다시 팔이 2개가 되게 하시오 

class grandfather:
     def __init__ (self):
          print("튼튼한 두팔")

class father1(grandfather):
     def __init__ (self):
          super().__init__()
          print("지식")

class father2(grandfather):
     def __init__ (self):
          super().__init__()
          print("지혜")

class grandchild(father1, father2):
     def __init__(self):
          super().__init__()
          print("난 행복해")

grandchild = grandchild()




6     클래스내부에게만 열려잇느 프라이빗 멤버
7     상속
8     오버라이딩
9     __call()__메소드
10    for 문으로 순회를 하룻 잇는 객체 만들기
11    추상 기반 클래스

9.6 오버라이딩

~ 보다 우선한다는 뜻이다
부모로 부터 상속받은 메소드를 다시 Override(재정의) 하겠다.

예제: 
class grandfather:
     def __init__(self):
          print("튼튼한 두팔")
class father2(grandfather):
     def __init__(self):
          print("지혜")

father2 = father2()
지혜도 주요지만 건강도 물려받고싶다면
class grandfather:
     def __init__(self):
          print("튼튼한 두팔")
class father2(grandfather):
     def __init__(self):
          super().__init__()
          print("지혜")

father2 = father2()

■ super() 에 대해서?
1.super()를 이용하면 부모클래스의 멤버에 접근을 할 수 있따.
2.super()를 이용하면 부모 클래스 명이 변경되어도 일일이 코드를 고치는 수고를 줄일 수 있다.
3.super()를 이요함녀 죽음의 다이아몬드 상속을 피할 수 있다. 

aa■ 9.6 데코레이터 사용법 
데코레이터의 사전적 의미? 꾸미다
데코레이터는 함 수를 꾸며주는 함수 
데코레이터는 함수의 능력을 확장 시켜준다. 
 
어떤 동작을 수행하기 전에 @ 로 시작하는 키워드를 사용해서 수행한다.

  • 데코레이터의 중요한 2가지 기능
  • 1. 함수를 강력하게 해준다.
  • 2. 공통적으로 사용하는 코드를 쉽게 관리하기 위해서 사용한다


  • 파이썬 함수의 4가지 특징
  • 1. 변수에 할당 할 수 있다.
  • 2. 다른 함수내에서 정의 될 수 있다. 
  • 3. 함수의 인자(매개변수)값으로 전달될 수 있다.
  • 4. 함수의 반환값이 될 수 있다. 


  1. 함수를 !!!  변수에 할당!!!!

def greet(name):
     return "Hello {} ".format(name) 

greet_someone = greet # 함수를 변수에 할당
print(greet_someone("scott")) 

  1. 다른 함수내에서 정의 할수 있어!!!!!
def greet(name):
    def greet_message():
       return 'Hello'
    return "{}  {}".format(greet_message(),name)

print(greet("scott"))

  1. 함수의 인자값으로 전달 될 수 있다!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
예: 
def greet(name):
     return "Hello {}".format(name)

def change_name_greet(func):
     name = "king"
      return func(name)

print( change_name_greet(greet))


  1. 함수의 반환값이 될 수 있다.


def greet (name):
     return "Hello {}".format(name)

 def uppercase (func):
     def wrapper(name):
          result = func(name)
          return result.upper()
     return wrapper

new_greet = uppercase(greet) ("scott")
print(new_greet)
print(new_greet("scott"))
문제167. 이름을 입력하고 함수를 실행하면
          해당하는 사원들의 직업이 소문자로 출력되는 함수를 생성하시오 !

함수1. 이름을 입력했을때 직업이 출력되는 함수 (find_job)
함수2. 문자를 입력했을때 소문자로 출력하는 함수 (lower_case)



def find_job(name):
    import pandas as pd
    emp = pd.DataFrame.from_csv("d:/data/emp.csv")
    job = emp[['job']][emp['ename'] == name].values[0][0]

    return job


def lowercase(func):
    def wrapper(name):
        result = func(name)
        return result.lower()

    return wrapper



new_find_job = lowercase(find_job)

print(new_find_job('SCOTT'))



■ 데코레이터 표현법을 보기전에 먼저 데코레이터와 같은
역할을 하는 함수를 생성

class greet(object):
    current_user = None
    def set_name(self,name): # current_user 라는 변수인 속성은 선언
        if name =='admin': #name 에 admin 이라는 문자를 담고
            self.current_user = name
        else:                  #admin 이 아니라면 권한이 없다는 에러를
            raise Exception("권한이 없네요") #발생시키는 함수

    def get_greeting(self,name): #name 이라는 매개변수에 admin 이
        if name == 'admin':  # 입력이 됬다면
            return "Hello {}".format(self.current_user)

                    #Hello 와 current_user 를 리턴하는
                    #함수


실행방법:

greet = greet()
greet.set_name('admin')
print(greet.get_greeting('admin'))

'Error cuz of object is not callable'

greet = greet()
greet.set_name('scott')
print(greet.get_greeting('scott')) # scott 은 안되거든?

문제168.어드민만 헬로 출력되게하라 

class greet(object):          # current_user 라는 변수인 속성을 선언

     current_user = None     # name에 admin이라는 문자가 들어오면
     def set_naem(self,name):     #current_user 에 admin 이라는 문자를 담고
          if name == 'admin':
               self.currnet_user = name
          else:                #admin이 아니라면 권한이 없다는 에러를 발생시킴
               raise Exception("권한이 없네요")

     def get_greeting(self,name):     # name이라는 매개변수에 admin이 입력되면
          if name == 'admin':
               return "Hello {}".format(self.current_user)
                                       # Hello와 current_user를 리턴하는 함수 
                                       

실행방법 :
greet = greet()
greet.set_name('admin')
print(greet.get_greeting('admin') )


위의 코드에서 중복되는 부분 즉 admin이 맞는지 확인하는 공통적인 코드를 하나의 함수로 만들어서 따로 떼어낼 수 있을 것 같다.



def is_admin(user_name):
     if user_name != 'admin':
          raise Exception("권한이 없다니까요 ")

class greet(object):
     current_user = None
     def set_name(self,name):
         is_admin(name)
         self.current_user = name

     def get_greeting(self,name):
         is_admin(name)
         return "Hello {}".format(self.current_user)

greet = greet()
greet.set_name('admin')
print(greet.get_greeting('admin') )
문제169. 이름을 넣어서 함수를 실행하면 해당 사원의 월급이 출력되게 함수를 생성하는데
     KING 만 월급을 볼 수 있게 하고 KING이 아닌 다른 사원들은 권한이 없다면서 볼 수 없게 에러가 나게 하시오 !

import pandas as pd
def is_admin(user_name):
     if user_name != 'KING' and :
          raise Exception("권한이 없다니까요 ")

class find_sal(object):
     current_user = None
     def set_name(self,name):
         is_admin(name)
         self.current_user = name

     def get_sal(self,name):
         is_admin(name)
         emp = pd.DataFrame.from_csv("d:/data/emp.csv")
         sal= emp[['sal']][emp['ename'] == name].values[0][0]
         return sal

find_sal  = find_sal ()
find_sal.set_name('KING')
print(find_sal.get_sal('KING') )

문제170.위에 is_admin(name) 이라는 함수를 사용해서 코드가 더 좋아졌다 하지만 데코레이터를 이용하면 함수가 더 
     좋아진다. 데코레이터를 써서 구현하시오 

def is_admin(func):
  def wrapper(*arg,**kwargs): # *arg 리스트의 가변 매개변수
                              # **kwargs 딕셔너리 가변 매개변수
    if kwargs.get('name') != 'admin':
        raise Exception("권한이 없다니까요 ")
    return func(*arg,**kwargs)
  return wrapper

class greet(object):
     current_user = None
     @is_admin
     def set_name(self,name):
         self.current_user = name

     @is_admin
     def get_greeting(self,name):
         return "Hello {}".format(self.current_user)

greet = greet()
greet.set_name(name='admin')
print(greet.get_greeting(name='admin') )

문제171. 문제169 코드를 데코레이터 함수를 이용해서 더 좋게 개선시키시오



import pandas as pd
def is_admin(func ):
  def wrapper(*arg,**kwargs): # *arg 리스트의 가변 매개변수
                              # **kwargs 딕셔너리 가변 매개변수
    if kwargs.get('name') != 'KING' :
        raise Exception("권한이 없다니까요 ")
    return func(*arg,**kwargs)
    if arg[1] == 'SCOTT' :
        raise Exception("스콧이당!")
    return func(*arg,**kwargs)
  return wrapper

class find_sal(object):
     current_user = None
     @is_admin
     def set_name(self,name):
         self.current_user = name

     def get_sal(self,name):
         emp = pd.DataFrame.from_csv("d:/data/emp.csv")
         sal= emp[['sal']][emp['ename'] == name].values[0][0]
         return sal

find_sal  = find_sal ()
find_sal.set_name(name = 'KING')
print(find_sal.get_sal(name = 'KING') )



import pandas as pd
def is_admin(func ):
  def wrapper(*arg,**kwargs): # *arg 리스트의 가변 매개변수
                              # **kwargs 딕셔너리 가변 매개변수
    if arg[1] == 'SCOTT' :
        raise Exception("스콧이당!")
    return func(*arg,**kwargs)
    if kwargs.get('name') != 'KING' :
        raise Exception("권한이 없다니까요 ")
    return func(*arg,**kwargs)
  return wrapper

class find_sal(object):
     current_user = None
     @is_admin
     def set_name(self,name):
         self.current_user = name

     @is_admin
     def get_sal(self,name):
         emp = pd.DataFrame.from_csv("d:/data/emp.csv")
         sal= emp[['sal']][emp['ename'] == name].values[0][0]
         return sal
find_sal  = find_sal ()
find_sal.set_name(name = 'KING')
print(find_sal.get_sal('SCOTT') )


객체와 클래스 (가장 중요한 단원) 


■ 어제 배운내용 복습
1. 클래스 멤버 2가지
                    -- public member
                    -- private member
2. 상속
     - 상속이 필요한 이유? 코드를 간결하게 하기위해서
       객체 지향언어를 제대로 활용하는 방법(object -oriented )
          1팀 : 로폿팔 클래스
          2팀 : 로봇다리 클래스
          3팀 : 로봇 몸체 클래스
          4팀 : 로봇 두뇌(인공신경망) 클래스 
          로봇팔에 버그가 있어 개선하는데 다리까지 영향을 끼친다 안돼!
          ==> 결국 유지보수 비용을 줄일수 있다.
          파이썬 (코어) 개발
          파이썬 개발자 중급 400 ~ 600 

  • 객체 (인스턴스)? 리스트 , 튜플, 딕셔너리 처럼 데이터를 다루기 위한 논리적 집합
                              ↓                                 ↓
                데이터를 어떤 형식으로 저장할 건가?    속성(변수)에 데이터를 넣고     
                                                   기능(함수)로 데이터를 다루는 역할


3만건의 영어 단어장 ----- 겨울왕국 스크립트 리스트 --->
       리스트                리스트                  full table scan 
                                                    (100초)

       딕셔너리              딕셔너리                index scan
       key:value            key:value               (1초)

  • 클래스란? 변수 + 기능 으로 구성된 논리적 집합 ! 
     인스턴스? 클래스(설계도) 를 실체화 한것

문제172. gun이라는 인스턴스를 생성하기 위해서 gun() 클래스를 생성하시오
     gun = gun()    # 총 설계도로 총을 실체화 시킴
     gun.charge(10) # 총알 10발 충전
     gun.shoot(3) 
       탕
       탕
       탕 
     7발 남았습니다. 

     gun.print() # 현재 총알이 얼마나 남았습니다. 
     7발 남았습니다. 

class gun:
    def __init__(self):
        self.bu =0
    def print(self):
        print('{} 발 남았습니다.'.format(self.bu))

    def charge(self,n):
        self.bu += n

    def shoot(self,a):
        for i in range(a):
            if self.bu > 0 :
                self.bu -= 1
                print ('탕 !')
            elif self.bu == 0 :
                print('총알이 없습니다')
                break

        print(self) 

gun = gun()    # 총 설계도로 총을 실체화 시킴
gun.charge(10) # 총알 10발 충전
gun.shoot(4)
gun.print()

예제2. 클래스를 사용하는 이유? 

class employee(object) 
  pass

emp_1 = employee()
emp_2 = employee()

예제2. 클래스를 사용하는 이유?

- 딕셔너리를 사용하는 경우

student = {'name': '김인호', 'year':2,'class':3,'student_id':35}

print('{}, {}학년 {}반 {}번'.format(student['name'],student['year'],student['class'],student['student_id']) )

- 클래스를 사용하는 경우 

class student(object):
     def __init__(self,name,year,class_num,student_id):
          self.name = name
          self.year = year
          self.class_num = class_num
          self.student_id = student_id

     def introduce_myself(self):
          return '{}, {}학년 {}반 {}번'.format(self.name, self.year, self.class_num,self.student_id)

student = student('김인호',2,3,35)

print (student.introduce_myself())


문제173. 위의 student 클래스를 다시 실행하는데 self 빼고해라

TypeError: introduce_myself() takes 0 positional arguments but 1 was given

introduce_myself()라는 메소드는 인자값을 안받게 만들어줘놓고 왜 하나를 줬느냐

인스턴스의 메소드를 호출하면 인스턴스 자기 자신인 self가 첫번째 인자로 자동으로 전달되기 때문이다.

def introduce_ myself():  # <-- self가 없습니다.

파이썬에서는 인스턴스의 메소드를 호출함녀 인스턴스 자기자신인 self가 첫번재 인자로 자동으로 전달되므로 
반드시

def introduce_myself(self)  # <=== self를 넣어줘야 한다. 

문제173. 자기 자신이 인스턴스의 메소드에 인자로 전달된다는 것이 어떤것인지 인스턴스를 통하지 않고
바로 클래스 introduce_myself를 직접 호출해서 확인하시오 

class student(object):
     def __init__(self,name,year,class_num,student_id):
          self.name = name
          self.year = year
          self.class_num = class_num
          self.student_id = student_id

     def static introduce_myself(self):
          return '{}, {}학년 {}반 {}번'.format(self.name, self.year,

self.class_num,self.student_id)

student1 = student('김인호',2,3,35)

print (student.introduce_myself())


■  self 를 왜 강조하느냐?

파이썬은 객체함수를 나타낼때 무조건 def(self,x,y)
이렇게 self를 첫번째 인자로 넣어야한다.
자바나 c++에서는 this 를 명시 안해도 되나 파이썬은 강제입니다.
 
■ static method ?
(정적 메소드 ) 

 - self를 매개변수로 받지 않는 메소드
 - 여러 인스터스가 공유해서 사용하는 메소드

  

class gun:
    def __init__(self):
        self.bu =0
    def print(self):
        print('{} 발 남았습니다.'.format(self.bu))

    def charge(self,n):
        self.bu += n

    def shoot(self,a):
        for i in range(a):
            if self.bu > 0 :
                self.bu -= 1
                print ('탕 !')
            elif self.bu == 0 :
                print('총알이 없습니다')
                break

        print(self) 

gun1 = gun()   
gun1.charge(10)
gun1.shoot(4)
gun1.print()

gun2 = gun()   
gun2.charge(10)
gun2.shoot(4)
gun2.print()

설명: gun1 총과 gun2총은 서로 다른 총입니다.
     같은 설계도를 사용했지만 별개의 총이다.
     별개의 총이 맞는지 확인해본다.
print(gun1)
print(gun2)
<__main__.gun object at 0x000000000C497828>
<__main__.gun object at 0x000000000C525D30>

print(gun1.__class__)
print(gun2.__class__)
<class '__main__.gun'>
<class '__main__.gun'>
 
 둘은 다른 메모리 주소값을 가지고 있어서 
같은 클래스를 쓰는 서로 별개의 오브젝트라는 것을 확인함

문제174. gun class 의 메소드들을 static method들로 변경해서 다시 총을 쏘시오 


class gun:

    bu = 0
    @staticmethod
    def charge(n):
        gun.bu += n

    @staticmethod
    def shoot(a):
        for i in range(a):
            if gun.bu > 0 :
                gun.bu -= 1
                print ('탕 !')
            elif gun.bu == 0 :
                print('총알이 없습니다')
                break

    @staticmethod
    def print():
        print('{} 발 남았습니다.'.format(gun.bu))

gun1 = gun()
gun1.charge(10)
gun1.shoot(3)
gun1.print()

gun2 = gun()
gun2.shoot(7)
gun2.print()
결과 :
탕 !
탕 !
탕 !
7 발 남았습니다.
탕 !
탕 !
탕 !
탕 !
탕 !
탕 !
탕 !
0 발 남았습니다.

문제175. static method로 선언한 클래스를 이용해서 인스턴스화한 두개의 총의 쏘는 메소드(shoot) 이 서로 같은 메모리를 쓰는지 다른 메모리를 쓰는지 확인하시오 


  • 9장 목차
  1. 객체와 클래스
  2. 클래스의 정의
  3. __init__() 메소드를 이용한 초기화작ㅇ업
  4. self에 대한 이해 
  5. 정적 메소드와 클래스 메소드 
  6. 클래스 내부에게만 ㅇ려려있는 프라이빗 멤버
  7. 상속
  8. 오버라이딩
  9. __call()__ 메소드 
  10. for문으로 순회를 할 히 있는 객체 만들기 
  11. 추상기반 클래스 


■9.10 마법의 __call__ 메소드

예제:
class sample(object):
     def __init__(self):
          print("전 생성하면 바로 생성이 돼요")

sample = sample()

설명: __init__ 메소드는 인스턴스를 생성하면 바로 실행이 된ㄷ.

예제2 :
class sampel2(object):
     def __call__(self):
          print("인스턴스에 괄호를 붙이면 제가 실행돼요")

sample2 = sample2()
sample()

클래스의 인스턴스를 함수처럼 호출하기 위해서 
클래스의 __call__ 이란느 매직 메소드를 정의했다
이 원리를 이용해서 클래스를 데코레이터로 구현할 수 있다
어제 우리가 데코레이터로 구현한건 클래스가 아니라 함수였다.

■ 클래스를 데코레이터로 구현하는 예제

from functools import wraps

class onlyadmin(obejct):               # 함수에 들어가는 매개변수의 문자열을 받아서
     def __init__(self,func):          # 대문자로 변환해줌
          self.func= func

     def __call__(self,*args,**kwargs):
          name = kwargs.get('name').upper()
          self.func(name)

def greet(name):
     print("Hello {}".format(name) )

greet(name = 'Scott')
결과 : Hello Scott

문제176. 위의 onlyadmin 데코레이터를 활용해서 find_job이라는 함수를 강력하게 하시오 ! 
find_job(name= 'scott')

당신의 직업은 ANALYST 입니다.



from functools import wraps
import pandas as pd

class OnlyAdmin(object):
    def __init__(self, func):  # 대문자로 변환해주며 함수를 실행해주는 클래스
        self.func = func

    def __call__(self, *args, **kwargs):
        name = kwargs.get('name').upper()
        return self.func(name)

@OnlyAdmin
def find_job(name):

    emp = pd.DataFrame.from_csv('d:/data/emp.csv')

    job = emp[['job']][emp['ename'] == name].values[0][0]
    return job


find_job(name='SCOTT')



  • 9장 목차
  1. 객체와 클래스
  2. 클래스의 정의
  3. __init__() 메소드를 이용한 초기화작ㅇ업
  4. self에 대한 이해 
  5. 정적 메소드와 클래스 메소드 
  6. 클래스 내부에게만 ㅇ려려있는 프라이빗 멤버
  7. 상속
  8. 오버라이딩
  9. __call()__ 메소드 
  10. for문으로 순회를 할 히 있는 객체 만들기 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  11. 추상기반 클래스 

■ 9.11 for 문으로 순회를 할 수 잇는 객체 만들기

Iterator 는 next() 메소드로 데이터를 순차적으로 호출하는 object이다. 

예제 :
for i in range(5) :
     print(i) 

우리가 당연하게 사용했던 위와 같은 for 문은 사실 range() 로 생성된 list 가 iterable 하기 때문에 순차적으로
member 들을 불러서 사용이 가능했던 것이다.

x = [1,2,3]
next(x)


■ 9.12 추상 기반 클래스 

상속일나 클래스의 재사용을 높임으로써
  1. 코드의 반복을 줄이고
  2. 유지보수 비용을 낮추는데 큰 역할을 한다

이러한 상속과 함께 객체지향(object-oriendted) 프로그램의 가장 중요한 특징중 하나가 다형성이다

다형성이란 클래스에 선언된 메서드가 상속 받은 클래스에서 같은 이름으로 
오버라이딩 되어 여러 형태로 동작함을 의미한다. 
예 :                동물 

               메소드 : 짓는다 (비어있는 메소드)
               ↙                        ↘
          고양이                         개

     짖는다 메소드 : 야옹               짖는다 메소드 : 멍멍 



                    동물   <--- 아직 덜 구체화된 상태 --> 그래서 객체화 시키기에는
                ↙          ↘
               고양이        개 <---- 구체화 된 상태

동물 넌 너무 추상적이야 그러니 너는 객체를 만들지마
!

그래서 추상 클래는 상속을 위해서 필요하긴 하지만 개체화해서는 안되는 클래스

추상 클래스는 추상 메소드가 있는 클래스를 말한다
추상 메소드는 바디(내용)가 없는 메소드이다.

추상 클래스를 상속 받는 자식 클래스에서 반드시 지켜줘야 할 사항은 ?

추상 클래스내에는 추상 메소드와 일반 메소드들이 있을 텐데 
그중에 추상 메소드는 반드시 가져와서 오버라이드 해야한다.

예제: 

from abc import ABCMeta, abstractmethod # 파이썬은 추상 클래스를 제공하지 않아서 import받아야한다.


class animal(object):

__metaclss__ = ABCMeta # 추상 클래스로 선언
@abstractmethod # 추상 메소드 선언
def bark(self):
     pass # 비어있는 메소드, 상속받는 자식들이 반드시 구현해야 하는 중요한 메서드

class cat(animal):

def __init__(self):
     self.sound = '야옹'


def bark(self):
     return self.sound


class dog (animal) :

def __init__(self):
     self.sound = '멍멍'
def bark(self) :
     return self.sound

cat = cat()

dog = dog()


print(cat.bark())

print(dog.bark())




문제177. 음료(beverage) 라는 추상클래스 생성하고
          아메리카노(americano)와 카페라떼 (caffelatte) 클래스를
          자식 클래스로 생성하시오 
          
          추상 클래스를  통해서 반드시 구현해야 하는 데메소드는 음료 가격임 












'PYTHON' 카테고리의 다른 글

English stopword , 영어 불용어  (0) 2018.09.18
gcp를 이용해서 jupyter notebook / jupyter lab 서버 만들기  (0) 2018.08.27
8장. 모듈  (0) 2017.09.10
7장. 함수  (0) 2017.09.10
6장. if 문과 loop문 (p126)  (0) 2017.09.10