python3 기초 5 - Classes

 


Classes

  • 클래스는 내가 원하는 Type의 object를 만들고 custom method를 적용 가능하게 한다.
  • 얘를 들면 아래처럼 course 를 위한 object을 만들고 내가 원하는 register, remove, buy등의 method를 정의할 수 있다.
courses.register()
courses.remove()
courses.buy()
  • 아래 예시에서 x 의 class는 int이다.
  • 파이썬에는 int라는 class가 있고 integer를 생성한다
  • list, dictionary 등과 같은 class도 있다.
  • 파이썬의 모든 object들은 class를 통해 생성된다
x = 1
print(type(x))

## <class 'int'>
  • Class : blueprint for creating new objects - Human
  • Object : instance of a class - John, Mary, Jack, ...

Creating Classes

  • class이름은 pascal naming convention을 따른다
  • 첫 글자는 대문자를 쓴다, _는 사용하지 않고 대문자로 단어를 구분한다(MyBlog)
  • class 에 속한 모든 function은 최소 하나의 parameter를 가진다.
  • 첫 parameter는 관용적으로 self를 사용한다
  • 아래 처럼 draw Function을 정의하면 Point class를 호출할때 draw method를 사용할수 있다
  • isinstance 는 특정 object가 특정 class의 instance인지 확인해준다
class Point:
		def draw(self):
				print("draw")

point = Point()
## point.draw 처럼 draw function을 method로 사용가능
print(type(point))                ## <class '__main__.Point'>
print(isinstance(point, Point))   ## True
print(isinstance(point, int))     ## False

Constructors

  • 아래와 같이 object을 생성할때 초기값을 지정하려면 constructor 라는 method를 사용해야한다.
  • __init__ 이라는 magic method를 사용해야하고 이걸 constructor라고 한다
  • 이 constructor가 처음 object을 정의하면 실행된다
  • class에서 정의하는 모든 method는 최소하나 parameter, self를 가져야한다.
  • self는 현재 object의 reference이다
  • Point(1, 2)와 같이 object을 만들때 python은 메모리에 Point object을 생성하고 self를 object의 reference로 설정한다
  • class를 정의하거나 method를 호출할 때의 argument를 class에서 쓸수 있는게 self가 있어서 인듯 하다.
  • object은 method도 가질 수 있고 object을 데이터를 포함하는 attribute도 가질 수 있다
  • point.draw(point) method와 같이 point 를 또 쓸 필요는 없다 python interpreter가 알아서 처리한다
class Point:
    def __init__(self, a, b):
        self.x = a       # __init__ method에서 입력받은 a를 attribut x에 저장
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
print(point.x)            # x는 Point의 attribute
point.draw()              ## Point (1, 2)

Class vs Instance Attributes

  • constructor에서 attribute a,b를 정의했으므로 Point object는 항상 default로 두 attribute를 가진다
  • attribute 는 class 정의 이후에 추가로 정의할 수 있다(point.c = 10)
  • 여기서 a, b, c 는 Instance attribute 이다
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
point.c = 10
print(point.x)
point.draw()

Instance Attribute

  • instance attribute는 Point instance나 Point object에 소속된다
  • 복수의 Point object가 정의되었을 때 각 Point object들은 서로 다른 instance attribute를 가질 수 있다
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
point.draw()

another = Point(3, 4)
another.draw()

Class attribute

  • Class attribute는 class 레벨에서 정의하고, 모든 object이 같은 attribute를 가진다.
  • class 정의 후 class attribute 값을 변경해도, 모든 object에 영향을 미친다
  • class attribute는 모든 class instance에 공유되고 값이 변경되면 모든 object에서 확인할 수 있다
class Point:
		default_color = "red"

    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

Point.default_color = "yellow"

point = Point(1, 2)
print(point.default_color)                    ## yellow
print(Point.default_color)                    ## yellow

another = Point(3, 4)
print(another.default_color)                  ## yellow

Class vs Instance Method

  • 아래에서 __init__draw 는 instance method 이다
  • point class를 쓸때 특정 object에 적용할 method가 필요할때 이다.
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
point.draw()
  • class method는 object이 존재하지 않은 상태에서 method를 쓸수 있다
  • 아래에서 Point(0, 0) 처럼 object을 정의하는 대신, zero()라는 method를 통해 바로 0,0을 가지는 object를 생성할 수 있다.
  • initialize 하는 과정이 아래보다 복잡하면서 반복적으로 활용해야하는 경우 factory method를 쓴다
point = Point(0, 0)
point = Point.zero()

Class method 만드는 법

  • cls 는 class의 약자
  • method 정의시 첫번째 파라미터는 관용적으로 cls 를 사용한다
  • cls는 class 자체를 참조한다
  • class method를 만드려면 classmethod 데코레이터를 사용해야한다
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		@classmethod
		def zero(cls):
				return cls(0, 0)

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point.zero()
point.draw()

## Point (0, 0)

Magic Methods

  • mehtod 이름 앞뒤로 두개 underscore를 쓴다
  • python interpreter에 의해 자동으로 호출된다
  • 아래 예시에서 Point(1, 2) object을 정의할때 __init__ method가 자동으로 호출됐다
  • 다양한 magic methods 는 python 3 magic methods 를 구글한다
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)

__str__

아래는 기본 str method의 결과

  • __maim__ : module
  • Point: class 이름
  • 0x105878f70 : 해당 object의 memory 주소
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
print(point.__str__)
print(point)

## <method-wrapper '__str__' of Point object at 0x10d8f7fd0>
## <__main__.Point object at 0x105878f70>
  • 아래 처럼 object의 기본 str 의 동작을 변경가능하다
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

		def __str__(self):
				return f"({self.x}, {self.y})"

		def draw(self):
				print(f"Point ({self.x}, {self.y})")

point = Point(1, 2)
print(point)

## (1, 2)

Comparing Objects

  • == 는 두 object 의 메모리 주소또는 reference를 비교한다
  • 아래에서 point와 other는 메모리에서 서로다른 object 를 referencing 하고 있기 때문에 다르다고 나옴
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

point = Point(1, 2)
other = Point(1, 2)
print(point == other)             ## False
  • object의 값을 비교하고 싶으면 compare magic method를 쓴다.
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

point = Point(1, 2)
other = Point(1, 2)
print(point == other)                  ## True
  • gt = greater than
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __gt__(self, other):
        return self.x > other.x and self.y > other.y

point = Point(10, 20)
other = Point(1, 2)
print(point > other)

Performing Arithmetic Operations

  • 산술 연산을 하려면 magic method를 활용해야한다.
class Point:
    def __init__(self, a, b):
        self.x = a
        self.y = b

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

point = Point(10, 20)
other = Point(1, 2)
print(point)              ## <__main__.Point object at 0x10eabffd0>
print(point + other)      ## <__main__.Point object at 0x10eabfc70>

combined = point + other
print(point.x)            ## 10
print(combined.x)         ## 11

Making Custom Containers

class Tagcloud():
    def __init__(self):
        self.tags = {}

    def add(self, tag):
        self.tags[tag] = self.tags.get(tag, 0) + 1

cloud = Tagcloud()
cloud.add("Python")
cloud.add("python")
cloud.add("python")
print(cloud.tags)              ## {'Python': 1, 'python': 2}
class Tagcloud():
    def __init__(self):
        self.tags = {}

    def add(self, tag):
        self.tags[tag] = self.tags.get(tag, 0) + 1

    def __getitem__(self, tag):
        return self.tags.get(tag, 0)

    def __setitem__(self, tag, count):
        self.tags[tag] = count

    def __len__(self):
        return len(self.tags)

    def __iter__(self):
        return iter(self.tags)

cloud = Tagcloud()
cloud["python"] = 10
print(len(cloud))        ## 1
cloud.add("Python")
cloud.add("python")
cloud.add("python")
print(cloud.tags)        ## {'python': 12, 'Python': 1}

댓글 쓰기

0 댓글