2019.03.21 TIL

(TIL은 스스로 이해한 것을 바탕으로 정리한 것으로 오류가 있을 수 있습니다)

# 질문에 답하기.

  1. 아래의 코드를 따라가면서 #에 따라 답해보기

코드를 통해 보는 class

>>>
>>>    def sum(a,b):            #1
>>>        return(a+b)
>>>
>>>    class Account:
>>>        
>>>        interest_rate = 0.08        #2         
>>>        num_of_account = 0                    
>>>        
>>>
>>>        @staticmethod                #3
>>>        def func(a,b):
>>>            return(a+b)
>>>
>>>        @classmethod                    #4
>>>        def string_constructor(cls, string):
>>>            data = string.split('_')
>>>            clnt_name = data[0]
>>>            balance = int(data[1])
>>>            return cls(clnt_name, balance)
>>>
>>>        @classmethod                        #5
>>>        def get_num_of_account(cls):
>>>            """
>>>            Account.get_num_of_account() ---> interger
>>>            return : 개설된 계좌 수
>>>            """
>>>            return cls.num_of_account
>>>
>>>        def __init__(self, clnt_name, balance):      #6
>>>            self.clnt_name = clnt_name              #7
>>>            self.balance = balance
>>>            Account.num_of_account += 1             
>>>
>>>        def deposit(self, money):                 #8
>>>            """
>>>            a.deposit(money) --> boolean
>>>            만약에 money > 0 입금성공
>>>            아니면 에러 메시지 출력 후 실패!
>>>            """
>>>            if money < 0:
>>>                print("입금은 0원 초과부터 가능합니다.")
>>>                return False
>>>            self.balance += money
>>>            return True
>>>
>>>        def withdraw(self, money):
>>>            """
>>>            a.withdraw(money) --> integer
>>>            return : 인출된 돈
>>>            만약 잔고가 모자라면 None
>>>            """
>>>            if money > self.balance:
>>>                print("인출할 돈이 잔액보다 많습니다.")
>>>                return None
>>>            self.balance -= money
>>>            return money
>>>
>>>        def transfer(self, other, money):           #9
>>>            self.balance -= money
>>>            other.deposit(money)
>>>
>>>        def __str__(self):                             #10
>>>            return f"{self.clnt_name} : {self.balance}"
>>>
>>>    if __name__ == "__main__"":
>>>        my_acnt = Account("greg", 5000)            #11
>>>        your_acnt = Account("john", 2000)
>>>    
>>>        print(Account.interest_rate)               #12
>>>        print(Account.get_num_of_account())        #13
>>>        print(my_acnt.interest_rate)               #14
>>>        print(my_acnt.get_num_of_account())        #15
>>>        print(Account.func(4,5))                   #16
>>>        print(type(Account.interest_rate))         #17
>>>        print(type(Account.get_num_of_account()))  #18
>>>        print(type(Account.get_num_of_account))    #19
>>>        print(type(my_acnt.deposit))               #20
>>>        print(type(Account.deposit))               #21
>>>        print(type(Account.func))                  #22
>>>
>>>        s = 'james_6000'                           #23
>>>        his_acnt = Account.string_constructor(s)
>>>        print(his_acnt)
>>>
>>>        my_acnt.deposit(7000)                      #24
>>>        print(my_acnt)
>>>
>>>        result1 = my_acnt.withdraw(3000)           #25
>>>        result2 = your_acnt.withdraw(3000)       
>>>        print(result1)
>>>        print(result2)
>>>
>>>        print(my_acnt)
>>>        print(your_acnt)
>>>
>>>
0.08
2
0.08
2
9
<class 'float'>
<class 'int'>
<class 'method'>
<class 'method'>
<class 'function'>
james : 6000
greg : 12000
인출할 돈이 잔액보다 많습니다.
3000
None
greg : 9000
john : 2000
>>>
>>>
>>>

#에 따라 정리하기

  1. #1 전역 함수

    • 어느 클래스에서도 속하지 않는다.
    • oop에서 제일 싫어하는 행동이다.
    • 최대한 관련있는 class에게 넣어주자.
  2. #2 클래스 멤버(class member)

    • 모든 객체가 공유한다.
    • 전역 변수(global variable)를 대체한다.
    • 클래스 바로 밑에 아무것도 적지 않고 적어주면 된다.
    • 모든 객체가 가지고 있을 필요는 없으나 모든 객체가 함께 공유해야 하는 것
      • ex: 이자율
    • 객체를 통해서도 클래스 멤버에 접근 가능하다.
    • 접근 방법 :
      • my_acnt.interest_rate : 객체를 통한 접근 방법
      • Account.interest_rate : 클래스를 통한 접근 방법
  3. #3 static method

    • 매서드처럼 보이지만 대놓고 함수이다. 전역함수
    • 전역 함수를 대체할 때 클래스메서드와 하나의 해결책이 될 수 있다.
    • 인자로 클래스나 객체를 받지 않는다. 함수의 정의만 클래스 A의 네임 스페이스에 있을 뿐 일반 함수와 같다.
  4. #4 클래스메서드(class method == @데코레이터)

    • 객체가 하나도 없는 상태에서도 호출이 가능하다.
    • cls가 self 대신 메모리 주소를 받는다.
    • 전역함수를 대체한다.
      • 전역함수를 대체할 때는 static method를 쓸 수 있다.
        • 아무것도 받지 않는다. 순수하게 함수다.
        • 사용방법(Account.func(5,4))
    • 관용적으로 cls를 받는다.
    • cls는 class를 받으므로 _init_ 와 같다.
  1. #5 클래스메서드(class method) + 대체 생성자

    • 객체가 하나도 없는 상태에서도 호출이 가능하다.
    • 전역 함수를 대체할 수 있다.
    • 원래 파이썬은 하나의 생성자만을 허용하지만 클래스메서드를 통해 해결 가능하다.
      • 대체 생성자(alternative constructor)가 될 수 있다.
      • 파이썬에서는 생성자를 하나만 가능하기때문에 여러가지 형태의 입력에 대응 할수 없다.
      • ex) 단체가입 "이름"_"초기값" ---> s = 'james_6000'
    • 접근방법
      • Account.get_num_of_account()
      • 객체를 통해서도 클래스 메서드에 접근이 가능하다.
  2. #6 생성자(constructor)

    • 파이썬에서는 오직 하나 존재한다.
    • _init_ : 객체(object)가 생성될 때 반듯이!! 한번 호출된다.
    • __ __ 은 파이썬에서 미리 쓰기로 해놓은 것이다.
  3. #7 인스턴스 멤버(instance member)

    • 인스턴스 멤버 == 상태정보 관리이다.
    • 각자의 객체가 가지는 값(값 = 상태정보)
    • init에 보면 변수가 나와 있다.
    • 생성된 object들은 같은 속성을 가지고 있으나 속성 값이 다르다.
    • Account.num_of_account ---> class멤버에 접근하는 방법
  4. #8 인스턴스 매서드(instance method)

    • object의 메서드로 봐도 된다.
    • class 입장에서는 function/ object입장에서는 메서드이다.
    • 객체가 할 수 있는 행동, 기능을 이야기 한다.
    • 인스턴스 메서드는 self를 꼭 써줘야 한다.
    • self는 해당 객체가 저장된 첫번째 주소를 가르킨다.
      • 즉 self는 생성된 객체 자기 자신을 가르킨다.
      • my_account.deposit(5000)이 실행될 떄 my_account를 self로 던져준다. self는 객체의 메모리 주소를 참조한다. 즉 자체참조이다.
  5. #9 message passing(메시지 패싱)

    • 나의 상태 정보와 함께 다른 객체의 상태 정보를 함께 변경해야 할 때
    • 다른 객체의 상태 정보(인스턴스 멤버)를 변경할 때는 반드시 상대 객체가 가진 메서드를 이용해야 한다.
    • 절대 하면 안되는 예)
      • self.balance -= money
      • other.balance += money
      • 다른 객체가 가진 메서드를 이용하지 않았다.
  6. #10 _str_(self)

    • my_acnt의 반환 포맷을 적어준다.
    • 이게 없으면 _main_.Account object at 0x10f512438처럼 반환
  7. #11 객체 생성

    • my_acnt(변수) = Account("greg", 5000) ==> class(매개변수)
    • 변수 = class(매개변수) 형태로 생성
    • 해당 객체는 해당 class의 인스턴스이다.
  8. #12 클래스 멤버 접근 방법

  9. #13 클래스 메서드 접근 방법

    • 클래스 메서드는 클래스 입장에서는 메서드지만(클래스의 행동 특정)
    • class입장에서 deposit과 같은 것은 함수이다.(클래스에 영상 x)
    • 하지만 객체 입장에서 deposit은 메서드이다.
    • print(type(my_acnt.deposit)) --- class 'method'
    • print(type(Account.deposit)) --- class 'function'
  10. #14 객체를 활용한 클래스 멤버 접근 방법

  11. #15 객체를 활용한 클래스 메서드 접근 방법

  12. #16 static method 접근 방법

  13. #17 클래스 멤버의 type

  14. #18 클래스 메서드 실행 했을 때의 type ---> int

  15. #19 클래스 메서드의 type

  16. #20 객체에서 메서드의 type

  17. #21 클래스에서 인스턴스 메서드의 type

  18. #22 static method의 타입

  19. #23 class method를 통해 대체 생성자를 만든 이유

    • 상황에 따라 전혀 예상하지 못한 형태의 값이 주어질 수도 있음
  20. #24 instance method 호출 방법(객체.method())

    • 객체에 self 인자는 넣어 줄 필요 없다.
    • class를 만들 때는 꼭 self를 써줘야 하지만 method를 호출하거나 객체를 생성할 때는 쓸 필요가 없다.
  21. #25 함수와 method의 차이점을 보여주는 예

    • 원래 withdraw라는 함수라면 입력이 3000원으로 같으므로 똑같이 나와야 한다.
    • 하지만 메소드는 내부에 가지고 있는 상태 정보가 다르기 때문에는 다르게 나온다.
    • 클로저에는 매개변수는 free variable이라고 부르는데
    • OOP에서는 인스턴스 멤버라고 부르는 것을 통해 상태정보를 관리한다.
    • 메서드 : 입력 + 인스턴스 멤버(상태정보, 데이터)에 의해 결과 값이 결정
      • 인스턴스 멤버(상태정보)를 바꾸는 역할을 하기도 한다.
    • 함수 : 입력에 의해 출력이 결정
      • 메서드처럼 사용하기 위해서는 call by reference 혹은 다른 변수에 할당
    • 메시지 패싱
      • 객체 간의 상호 작용 --> 객체가 가지고 있는 멤버 값(데이터, 상태 정보)의 변화
      • 내가 가진 건 1000이 적어지면 너에게 1000이 늘어난다.
      • interaction이 반드시 메서드에 의해 이루어져야 한다.
      • .은 속성을 가지고 온다는 뜻이다. 속성에는 인스턴스 멤버와 인스턴스 메서드가 있다.

절차지향 vs 객체지향

###procedural vs object-oriented

2개다 추상화를 하는 기법이다.

procedural : 함수를 이용해 추상화를 했다. 추상화의 도구로 함수를 이용 (절차지향)

  1. 이 프로그램은 어떤 일을 하는가?
  2. 기계와 비슷한 사고 방식
  3. 함수를 이용

object-oriented : 객체를 통해 추상화를 했다.

  1. 현실 세계(에 존재하는 객체(object)를 어떻게 모델링(modeling)할 것인가?
    1. 객체(object) : 사람, 동물, 자동차 등을 어떻게 프로그램으로 모델링 할 것인가?
  2. 사람과 비슷한 사고 방식
  3. 객체를 이용

객체 vs 인스턴스

메모리 상으로는 완벽히 같다.
하나를 볼 때는 객체로 보고
이 객체는 특정 클래스의 인스턴스라고 부른다.
why? 어떤 클래스에서 나왔는지 알고 싶을 때 - 클래스에 집중해서 말할 때

object란?

  1. 관련 있는 변수와 함수를 한곳에 모아(bundling) 놓은 곳(메모리의 영역)
    1. 변수 - 상태정보
    2. "관련 있는" 변수, 함수" "한곳에 모아" 가 중요하다.
  2. class를 통해 생성되므로 class의 속성을 가지고 있어야 한다.
  3. 속성
    1. instance member(변수)
      1. 각자의 객체가 가지는 값(값 = 상태정보)
      2. init에 보면 변수가 나와 있음
      3. 같은 속성을 가지고 있으나 속성 값이 다르다.
    2. instance method(함수)
      1. 객체가 할 수 있는 행동, 기능

—> 절차지향에서는 전체 프로그램을 다 봐야하지만.
—> 객체지향에서는 단위로 프로그램을 유추해볼 수 있다.

중요한 이해

클래스의 메모리와 객체의 메모리는 모두 다르다.
객체마다 모두 다른 메모리 공간을 가지고 있다.
각 객체가 인스턴스 멤버를 따로 가지고 있고 메서드 역시 각자 가지고 있다고 생각하는게 좋다.
my_acnt
balance / clnt_name / deposit / withdraw / transfer
your_acnt
balance / clnt_name / deposit / withdraw / transfer

미션 : 클래스를 쓰지 않고 OOP 구현

클래스를 쓰지 않고.
(클래스 멤버, 메소드 제외).
어떤 객체를 만들 수 있어야 하고
그 객체에 대해 함수를 호출하여 돈을 입금
init / deposit / withdraw / transfer.
하나의 unit을 딕셔너리로 고정한다.
class라는 유닛 대신에 딕셔너리로 묶어라.

def person_init(name, money):
    obj = {'name': name, 'money': money}
    obj['give_money'] = Person[1]
    obj['get_money'] = Person[2]
    obj['show'] = Person[3]
    print(obj)
    # --->    obj = {'name' : name, 'money' : money , 'give_money' : Person[1], 'get_money' : Person[2], 'show' : Person[3]}
    return obj


def give_money(self, other, money):  # 3
    self['money'] -= money
    other['get_money'](other, money)  # 4


def get_money(self, money):
    self['money'] += money


def show(self):
    print('{} : {}'.format(self['name'], self['money']))


Person = person_init, give_money, get_money, show

if __name__ == "__main__":
    # 객체 생성
    g = Person[0]('greg', 5000)  # 5
    j = Person[0]('john', 2000)

    g['show'](g)
    j['show'](j)
    print('')

    # 메시지 패싱
    g['give_money'](g, j, 2000)  # 6

    g['show'](g)
    j['show'](j)

2019.03.20 TIL

(TIL은 스스로 이해한 것을 바탕으로 정리한 것으로 오류가 있을 수 있습니다)

# 질문에 답하기.

  1. 객체란? (클래스, 객체, 인스턴스, 프로퍼티, 메소드에 대해)

class - 객체를 만들어 내기 위한 틀

class는 객체를 만들어내기 위한 약속이다.
class는 객체의 속성(property)과 동작(method)을 정의한다.

object - class라는 틀을 가지고 만들어낸 실물(ex. 자동차)

파이썬에서의 객체

  • 컴퓨터가 보는 객체 : 클래스를 이용해 만들어진 변수와 함수를 가진 메모리 공간
  • 우리가 보는 객체 : 현실 세계의 사물을 모델링 한 것

object란?

  1. 관련 있는 변수와 함수를 한곳에 모아(bundling) 놓은 곳(메모리의 영역)
    1. 변수 - 상태정보
    2. "관련 있는" 변수, 함수" "한곳에 모아" 가 중요하다.
  2. class를 통해 생성되므로 class의 속성을 가지고 있어야 한다.
  3. 속성
    1. instance member(변수)
      1. 각자의 객체가 가지는 값(값 = 상태정보)
      2. __init__에 보면 변수가 나와 있음
      3. 같은 속성을 가지고 있으나 속성 값이 다르다.
    2. instance method(함수)
      1. 객체가 할 수 있는 행동, 기능

—> 절차지향에서는 전체 프로그램을 다 봐야하지만.
—> 객체 단위로 프로그램을 유추해볼 수 있다.

컴퓨터 프로그램은 정보가 어떤 경로(네트워크, 디스크, 센서, 사람의 손 등)로 입력되든지, 결국은 그 정보를 메모리 위에 올린 뒤에 처리한다. 음식을 어떻게 준비하든지 결국은 식탁 위에 올려서 먹는 것처럼 말이다. 메모리는 그냥 비트(숫자)를 나열한 단순하고 넓은 판이기 때문에, 메모리 위에 올려 둔 정보를 의미 있는 덩어리로 묶어두기 위한 단위가 필요하다. 파이썬에서는 객체(object)라는 단위로 메모리 위의 정보를 관리한다.
객체에는 값(value)·유형(type)·정체성(identity)이라는 세 특성이 있다. 값은 메모리에 기록된 내용이다. 가변 객체는 값이 바뀔 수 있지만 불변 객체는 값이 바뀌지 않는다. 유형은 데이터의 종류로, 유형에 따라 그 값을 어떻게 읽고 다루어야 할지가 결정된다. 정체성은 각각의 객체를 식별하기 위한 고유번호로, 객체가 메모리 속에서 위치한 주소 값이기도 하다. 값과 유형이 동일한 데이터가 데이터가 메모리 공간에 여러 개 존재할 수 있지만, 이들은 서로 별개의 객체이며 정체성이 서로 다르다.

ex)

a = 10
b = 10
a == b (객체의 값 비교)
type (a) == type(b) (두 객체의 유형 비교)
id(a) == id(b) (두 객체의 정체성 비교)

추가 개념정리

a = 10
b = a
a += 10
print(b) 

위를 계산하게 되면 a라는 이름은 10이라는 값 객체를 가르키게 되고 b=a라고 할당해주었을 때 b는 a를 가르키는게 아니라(이중 할당 x) a의 값 객체를 가르킨다.
따라서 a += 10을 해주었을 때 integer은 immutable이므로 a는 새로운 값객체 20을 만들어 가르킨다. 따라서 10을 가르키고 있는 b는 변하지 않는다. 하지만 call by reference에서는 b는 a의 주소를 참조하므로 b = 20이 된다.

추가 개념정리

a = [1,2,3]
b = a
a += [4,5,6]
print(b)

일 때 b의 값
a 는 리스트를 가르키고 있고 리스트는 대표적인 mutable이므로 a가 가르키는 값 객체가 [1,2,3,4,5,6]으로 바뀌고 그에 따라 b역시 바뀜

def func(a)
     a[2] = 0
a = [1,2,3]
func(a)
print(a).  #[1,0,3]     

개념 정리

  • 객체: 메모리에 존재하는 개별 데이터를 가리키는 개념
  • 객체의 값: 객체를 통해 구할 수 있는 정보 그 자체. 가변 객체는 값이 바뀔 수 있다.
  • 객체의 유형: 객체가 어떤 범주에 속하고 어떻게 다뤄야 하는지를 구별하기 위한 분류. 파이썬에서는 클래스로 유형을 나타내며, type() 함수로 구할 수 있다.
  • 객체의 정체성: 객체를 다른 객체와 구별하기 위한 고유번호이자, 메모리 상의 위치. id() 함수로 구할 수 있다.
  • 변수: 객체에 붙인 이름. 한 객체에 여러 개의 이름을 붙일 수도 있다.

https://python.bakyeono.net/chapter-8-2.html 참고

property - object의 속성 (ex. 블랙박스, 오디오, 쿨시트 등등)

obj = {} 라는 빈 객체를 만들고
여기서 obj.a = 10 을 해주면 (in javascript)
a라는 property에 10이라는 값이 들어가게 된다. 따라서 obj이라는 객체는 10이라는 속성을 가지고 있고
그 값에 접근가능한 이름이 a이고 이 a는 활용 가능한 10이라는 값을 지니게 된다.

method - object의 동작을 나타낸다. (ex, 간다, 멈춘다, 가속, 후진)

메소드는 객체가 가지고 있는 동작이다. 함수와 메소드는 기본적으로 일련의 동작을 실행한다는 점에서 동일하나,
메소드는 특정 객체가 가지고 있는 동작을 가지고 있고, 메소드를 실행하기 위해서는 객체를 통해야만 실행가능하다.
그에 비해 함수는 함수 자체가 그 동작을 정의한 객체이다.

instance - 객체가 어떤 class에 속할 때 그 객체를 그 class의 instance라고 부른다.

파이썬에서 객체라고 하면 메모리에 올려져 있는 단위라고 볼 수 있다.

year = 2019 라고 하면
2019라는 값을 가지고 있는 객체가 메모리에 올라가고
year은 변수로서 2019라는 객체를 가리키고 있는 것이다. (즉 객체에 이름을 붙여 준 것이다.).
이 year이라는 이름을 가진 객체는 2019라는 프로퍼티를 가지고 있다.
그리고 2019는 int라는 클래스의 인스턴스이다.

'Python' 카테고리의 다른 글

파이썬 14. 코드를 통해 보는 class  (0) 2019.12.28
파이썬 13. openpyxl  (0) 2019.12.28
파이썬 11. decorator  (0) 2019.12.28
파이썬 10. filter, map, reduce  (0) 2019.12.28
파이썬 09. lambda  (0) 2019.12.28

+ Recent posts