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__
: modulePoint
: 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 댓글