행위

Python class

DB CAFE

DBCAFE (토론 | 기여)님의 2020년 3월 23일 (월) 13:10 판
thumb_up 추천메뉴 바로가기


1 클래스 용어[편집]

  • class : 멤버와 메쏘드를 갖는 객체
  • class instance : 클래스를 호출하여 만들어지는 객체
  • member : 클래스의 변수
  • method : 클래스의 함수
  • attribute: 속성, 멤버 와 메쏘드의 전체
  • supperclass : base class라고 하며 최상위 클래스
  • subclass : derived class라고 하며 수퍼클래스로터 상속된 하위 클래스
  • inheritance : 상속, A클레스를 수퍼클레스로 하는 클레스B는 B is-a A 관계라고 함
  • Multiple Inheritance : 다중상속, 두개 이상의 클래스로 부터 상속 받음.
  • Polymorphism : 다형성, 상속관계내의 다른클래스의 인스턴스들이 같은 멤버 함수 호출에 대해 각각 다르게 반응하도록 하는 기능
  • Encapsulation : 은익,메쏘드와 멤버를 클래스 내에 포함시키고 외부에서 접근할수 있도록 인터페이스만을 공개하고 다른 속성은 숨기는 것
  • Composition : 합성, X라는 객체가 클래스A안에 포함되어 A의 각종 메소드를 구현하는데 사용됨. A가 x를 포함하므로 has-a 관계라 함.

2 파이썬 클래스 특징[편집]

    • 클래스는 객체의 구조와 행동을 정의.
    • 객체의 클래스는 초기화를 통해 제어.
    • 클래스는 복잡한 문제를 다루기 쉽도록 만듭니다.

3 클래스 정의[편집]

클래스를 작성하기 위해서는 class 키워드 사용하여 새로운 클래스 생성.

Python의 대부분 네이밍컨벤션이 단어와 단어사이에 _ 를 넣는다. 하지만 클래스의 네이밍컨벤션은 CamelCase 를 사용.

class CustomClass:
      def __init__(self, param):
          .......

3.1 클래스 생성 연습[편집]

에디터에서 airtravel.py 파일을 생성합니다.

클래스 생성은 아래와 같이 class 키워드 및 클래스의 이름을 입력하여 생성.

class Flight:
      pass

생성한 클래스는 REPL(read-eval-print loop,사용자의 입력 후 실행하고 결과를 반환시키는 프로그래밍 환경)에서 아래와 같이 import할 수 있습니다.

>>> from airtravel import Flight
  >>> Flight
  <class 'airtravel.Flight'>

3.2 클래스 객체 생성 및 변수에 할당[편집]

  • 새로운 객체를 생성하기, java나 C# 등의 다른 언어와 다르게 new 키워드가 없다.
>>> f = Flight()
  >>> type(f)
  <class 'airtravel.Flight'>

4 클래스 메소드 작성[편집]

메소드란? 클래스 내의 함수

  • 메소드 작성하기
class Flight:
      def number(self):
          return 'KR949'

4.1 인스턴스 메소드의 접근[편집]

인스턴스 메소드란? 객체에서 호출되어질수 있는 함수

  • 인스턴스의 메소드 사용
>>> from airtravel import Flight
  >>> f = Flight()
  >>> f.number()
  'KR949'

파이썬 메서드의 첫번째 파라미터명은 관례적으로 self 라는 이름을 사용합니다.

호출 시 호출한 객체 자신이 전달되기 때문에 self라는 이름을 사용하게 된 것

이를 이용하여 클래스에서 바로 메소드로 접근하면서 위에서 할당한 Flight의 객체 f를 파라미터로 전달함으로써 똑같은 결과값 얻습니다.

    • 클래스의 내부에 self 파라미터가 포함되는데 이를 이용한 접근법
>>> Flight.number(f) # f는 Flight객체
  'KR949'

5 생성자와 초기화자[편집]

    • 생성자(constructor)
 f = Flight() 

생성자로 객체생성을 호출받으면 먼저

  1. __new__ 를 호출하여 객체를 생성할당하고,
  2. __new__ 메소드가 __init__메소드를 호출

하여 객체에서 사용할 초기값들을 초기화하게됩니다.


간혹 여러 자료들을 보면.. __init__ 메소드를 생성자로 소개하는 경우가 있는데, 그렇지 않습니다.

자료 https://stackoverflow.com/questions/6578487/init-as-a-constructor

일반적으로 파이썬에서 클래스를 만들 시 __init__ 메소드만 오버라이딩하여 객체초기화에만 이용합니다.

5.1 생성자/초기화자 예제[편집]

5.1.1 생성자 / 초기화 실행 순서 확인[편집]

class Flight:
  	#초기화자 
	def __init__(self):
	  print('init')
	  super().__init__()

	# 생성자     
	def __new__(cls):
	  print('new')
	  return super().__new__(cls)

	# 메소드 
	def number(self):
	  return 'KR949'
  1. REPL에서 객체 생성
  2. __new__가 클래스 자체를 받으며 할당하게되고
  3. __init__가 self를 받으며 객체의 내부에서 사용할 속성을 초기화.
>>> from airtravel import Flight
  >>> f = Flight()
--- 결과 -- 
  new
  init

Flight클래스를 수정후 다시 실행 .

  1. __new__ 메소드는 자동으로 실행되므로 제거합니다.
  2. __init__ 메소드에 코드를 수정합니다.

아래의 코드에서 self._number 로 할당했는데 변수명의 _ 의 의미는 다음과 같습니다.

    • 내부적으로 사용되는 변수
    • 파이썬기본 키워드와 충돌을 피하기 위한 변수

_ 관련 네이밍컨벤션에 관련한 자료 https://spoqa.github.io/2012/08/03/about-python-coding-convention.html https://www.python.org/dev/peps/pep-0008/#naming-conventions

class Flight:
      def __init__(self, number):
          self._number = number
            
      def number(self):
          return self._number

다시 REPL에서 확인 합니다.

>>> from airtravel import Flight
   >>> f = Flight(5)
   >>> f.number()
   5
   >>> f._number
   5

6 접근제어자[편집]

Python은 기본적으로 다른언어에 있는 접근제어자(public, private, protected)가 없음. 기본적으로 모두 Public

6.1 초기화자(__init__)객체의 불변성을 확립(유효성검증 수행)[편집]

일반적으로 초기화자(__init__)에서 객체의 불변성을 확립하는 것이 좋습니다.

객체 생성시 들어올 값에 대해서 __init__에서 Validation을 수행합니다.

비행기 번호는 앞에 두글자는 영문이어야하며 대문자입니다.

그리고 뒤에 세번째 글자부터 마지막까지는 양의 정수여야합니다.

Flight클래스를 다음과 같이 변경해봅니다.

객체를 생성시 규칙에 맞지 않는 값이 들어오면 ValueError를 발생시킵니다.


class Flight:
    
      def __init__(self, number):
          if not number[:2].isalpha():
              raise ValueError("첫 두글자가 알파벳이 아닙니다.")
          if not number[:2].isupper():
              raise ValueError("첫 두글자가 대문자가 아닙니다.")
          if not number[2:].isdigit():
              raise ValueError("세번째 글자 이상이 양의 숫자가 아닙니다.")
          self._number = number
            
      ...생략
  >>> from airtravel import Flight
  >>> f= Flight("abc")
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/Users/Blidkaga/Documents/CodeLab/Python_Basic/airtravel.py", line 11, in __init__
      raise ValueError("첫 두글자가 대문자가 아닙니다.")
  ValueError: 첫 두글자가 대문자가 아닙니다.
  >>> f= Flight("AB0")
  >>> f= Flight("AB001")

7 비공개 속성[편집]

_ 언더바 한 개는 내부적으로만 사용되는 변수다라고 알지만, 사실 값을 얻어올수도 있고 할당도 가능합니다.

코딩컨벤션으로 파이썬을 쓰는 사람들이면 내부적인 변수구나 하고 알고 있을 뿐..

>>> f= Flight("AB001")
  >>> f._number
  'AB001'
  >>> f._number = 'abc'
  >>> f.number()
  'abc'
원천적인 접근을 막으려면 __ 더블 언더바(던더바)를 사용하면 막을 수 있습니다.

7.1 언더바를 던더바로 변경[편집]

_name 변수를 __name으로 변경하였습니다.

class Flight:
    
      def __init__(self, number):
          if not number[:2].isalpha():
              raise ValueError("첫 두글자가 알파벳이 아닙니다.")
          if not number[:2].isupper():
              raise ValueError("첫 두글자가 대문자가 아닙니다.")
          if not number[2:].isdigit():
              raise ValueError("세번째 글자 이상이 양의 숫자가 아닙니다.")
          self.__number = number
    
      def number(self):
          return self.__number

7.2 결과 확인.[편집]

number()인스턴스 메소드를 통해서 내부에서는 접근 가능한 모습을 보이나, 객체 f의 속성으로 접근 시 에러가 발생합니다.
>>> from airtravel import Flight
  >>> f= Flight("AB001")
  >>> f.number() 
  'AB001'
  >>> f.__number
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
  AttributeError: 'Flight' object has no attribute '__number'

8 파이썬은 메소드 오버로딩이 없다.[편집]

메소드 오버로딩이란? : 하나의 클래스 내부에서 메소드 명칭은 똑같고, 인자를 다르게하는 형태를 허용합니다.

Java코드는 아래와 같은 코드를 허용합니다.

class Adder{  
      static int add(int a,int b)
      {
          return a+b;
      }  
      static int add(int a,int b,int c)
      {
          return a+b+c;
      }  
  }

파이썬은 메소드 오버로딩이 없습니다.

아래와 같은 코드가 있다면 첫번째 show는 무시되고, 두번째 show만 유지됩니다.

class Korea:
    
      def __init__(self, name,population, captial):
          self.name = name
          self.population = population
          self.capital = captial
    
      def show(self):
          print(
              """
              국가의 이름은 {} 입니다.
              국가의 인구는 {} 입니다.
              국가의 수도는 {} 입니다.
              """.format(self.name, self.population, self.capital)
          )
    
      def show(self, abc):
          print('abc :', abc)

결과

 >>> from inheritance import *
 >>> a = Korea('대한민국',50000000, '서울')
 >>> a.show()
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: show() missing 1 required positional argument: 'abc'


9 클래스 내부에서 메소드 호출[편집]

class MyClass:
	def set(self,v):
		self.value =v
	def incr(self):
		self.set(self.value+1)
	def put(self):
		print(self.value)

c = MyClass()
c.set('egg')
c.put()

10 생성자 와 소멸자[편집]

__init__ #생성자 __del__ #소멸자