* 정적 메소드와 클래스 메소드
인스턴스 메소드는 인스턴스(객체)에 속한 메소드를 말한다.
메소드는 클래스에 정의하는데 인스턴스에 속하다니 무슨말인가 ?
여기서 인스턴스에 속한다 라는 표현은 인스턴스를 통해 호출가능하다 라는 뜻이다. 그럼 클래스에 속한(클래스를 통해 호출 가능한) 메소드도 있을 것이다. 이 두개의 메소드가
정적 메소드와 클래스 메소드이다.
정적메소드는 @staticmethod 데코리에터로 수식하며, self매개변수 없이 정의한다.
class 클래스이름 :
@staticmethod
def 메소드이름( 매개변수 ):
pass
self매개변수는 사용하지 않는다.
ex) 정적메소드
1 2 3 4 | class Calculator: @staticmethod def plus(a,b): return a+b |
obj = Calculator()
obj.plus(3,5)<-- 대게는 이렇게 인스턴스를 만들어 호출하지 않는다.
a = Calculator.plus(3,4) <-- 이렇게 호출하는 것이 보통이다.
ex) 사용 예
1 2 3 4 5 6 7 8 9 10 11 12 | class Calculator: @staticmethod def plus(a,b): return a+b @staticmethod def minus(a,b): return a-b print("{} + {} = {}".format(7,4,Calculator.plus(7,4))) print("{} - {} = {}".format(7,4,Calculator.minus(7,4))) |
정적 메소드는 self매개변수를 전달받을 방법이 없으므로 객체/인스턴스의 변수에 접근할 수 없다.
* 클래스 메소드
클래스를 통하여 호출한다.
인스턴스를 통해서도 호출이 가능하다.
첫 매개변수로 클래스 객체를 전달한다.
관용적으로 첫 매개변수를 cls로 사용한다.
클래스 메서드는 @classmethod장식자에 의해서 선언된다.
class 클래스이름 :
#...
@classmethod
def 메소드이름(cls):
pass
매개변수로 self가 인스턴스를 나타냈다면 cls는 클래스를 나타낸다.
ex) 클래스 메소드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Calc: var1 = 1 var2 = 2 def InstanceAdder(self): print("인스턴스 메소드:",self.var1 + self.var2) @classmethod def classMethod(cls): print("클래스메소드:",cls.var1 + cls.var2) #print("인스턴스변수사용:",self.var1 + self.var2) 에러 #Calc.InstanceAdder() #인스턴스메소드이기 때문에 에러 Calc.classMethod() #클래스.메소드 접근가능 mycal = Calc() mycal.InstanceAdder() mycal.classMethod() # 인스턴스도 클래스메소드 사용가능 |
출력결과
클래스메소드: 3
인스턴스 메소드: 3
클래스메소드: 3
11행 : 인스턴스변수 사용 self는 사용할 수 없다.
16행 : Calc클래스의 instanceAddr(self)메소드는 인스턴스메소드이기 때문에 사용할 수 없다.
* 공개, 비공개 속성(public & private)
클래스 안에서만 접근가능한 멤버를 private멤버라고 한다.
클래스 안과 밖에서 모두 접근 가능한 멤버를 public멤버라고 한다.
메서드에도 public, private 속성 적용이 가능하다.
프라이빗 속성은 멤버 혹은 메소드 앞에 __ 를 붙인다.
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class tes: def __init__(self): self.public="public" self.__private = "private" def internal(self): print(self.public) print(self.__private) >>> a=tes() >>> a.internal() public private >>> print(a.public) public >>> print(a.__private) Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> print(a.__private) AttributeError: 'tes' object has no attribute '__private' |
11행 인스턴스를 만들어주고, 13행에서 실행을 하고 있다. 같은 클래스의 멤버끼리 자유롭게 접근이 된다.
하지만 18행은 __private 데이터 속성이 아예 존재하지 않는 것처럼 보이기 때문에 에러가 난다.
* 상속 *
클래스는 상속을 통해서 부모클래스의 속성 및 기능을 물려받는다.
상속에 관련된 클래스는 부모(기반,상위) 클래스와 자식(파생,하위)클래스로 구분된다.
자식클래스는 부모클래스의 변수, 메소드, 생성자등을 이용할 수 있다.
자식클래스는 상속받은 기능외에 자신만의 기능을 추가할 수 있다.
자식클래스는 상속받은 기능을 수정할 수 있다. (메소드 오버라이딩,재정의) => 다형성(그림판)
class 기반(부모)클래스:
#멤버 정의
class 파생(자식)클래스(기반(부모)클래스):
# 아무 멤버를 정의하지 않아도 기반 클래스의 모든 것을 물려받아 가지게 된다.
# 단 프라이빗 멤버는 제외다.(__로 시작하는 멤버)
ex) 상속
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Animal: def __init__(self,name,age): self.name = name self.age = age def printInfo(self): print("이름:",self.name) print("나이:", self.age) def play(self): print("놀기") def parentMethod(self): print("__prarentMethod__") class Dog(Animal): pass >>> mydog = Dog("해피",7) >>> mydog.printInfo() 이름: 해피
나이: 7 >>> mydog.play() 놀기 |
Dog클래스가 스스로 구현한 메소드는 없지만, Animal로부터 상속받은 메소드는 가지고 있다.
super
부모클래스의 객체 역할을 하는 프록시(Proxy)를 반환하는 내장 함수이다.
ex)
1 2 3 4 5 6 7 8 | class A: def __init__(self): print("hh") class B(A): def __init__(self): super().__init__() |
즉, 자식클래스의 메소드 안에서 부모클래스의 메소드를 호출할 때 !
super를 쓰면 기반 클래스가 다른 클래스로 교체되거나 수정되어도 파생 클래스가 받는 영향을 최소화 할 수 있다.
오버라이딩
기반(부모) 클래스로부터 상속받은 메소드를 다시 정의한다.(재정의)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class Animal: def __init__(self,name,age): self.name = name self.age = age def printInfo(self): print("이름:",self.name) print("나이:", self.age) def play(self): print("놀기") def parentMethod(self): print("__parentMethod__") class Dog(Animal): def play(self): # 메소드 오버라이딩(재정의) super().play() # 부모의 메소드 호출 print("신나게 놀기") # 재정의 def callerMethod(self): super().parentMethod() #부모의 메소드 호출 >>> mydog = Dog("해피",7) >>> mydog.printInfo() 이름: 해피 나이: 7 >>> mydog.play() 놀기
신나게 놀기 >>> mydog.callerMethod() __parentMethod__ |
12~14행 : 오버라이딩을 하면서, 부모의 메소드를 활용할 수 있는 방법이다.!
다중상속
자식 하나가 여러부모로부터 상속을 받는 것!
1 2 3 4 5 6 7 8 9 10 11 | class A: pass class B: pass class C: pass class D(A,B,C): #다중상속 pass |
클래스 D가 A,B,C로부터 상속을 받고있다.
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class A: def method(self): print("A") class B(A): # 부모가 A def method(self): print("B") class C(A): # 부모가 A def method(self): print("C") class D(B,C): # 부모가 B,C pass |
위의 예제는 일명 다이아몬드상속?이라고도 한다.
A A 부모클래스
B C B,C는 A가 부모클래스
D D는 B,C가 부모클래스
A는 method()라는 메소드를 구현하고있고, B와 C는 A로부터 상속을 받았다. 하지만 B와 C는 method()메소드를 재정의 하고 있다.
이 때 D는 B와 C중 누구의 method()를 물려받을 것인가 ? 그 정답은 B이다.
부모클래스의 목록에서 가장 앞에 있는 클래스의 메소드를 물려주고 있기 때문이다.
* 추상클래스
클래스 내에 한개 이상의 추상메소드가 있어서 인스턴스 객체가 생성할 수 없는 클래스
하위클래스가 반드시 구현해야할 메소드를 가지고 있다.
abc(Abstract Base Classes)모듈을 import하고 AbC Meta클래스를 지정한 뒤, @abstractmethod 장식자를 이용하여서 추상메소드를 만든다.
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from abc import * class StudentBase(metaclass=ABCMeta): @abstractclassmethod #추상메소드 def study(self): pass @abstractclassmethod def goToLibrary(self): pass class Student1(StudentBase): def study(self): # 추상메소드를 오버라이딩 print("공부를한다.") def goToLibrary(self): # 추상메소드를 오버라이딩 print("도서관에 간다.") class Student2(StudentBase): pass std1=Student1() std1.study() std1.goToLibrary() #std2=Student2() # goToLibrary메소드를 재정의 하지 않아서 에러 #stB = StudentBase() 추상클래스는 인스턴스를 만들지 않는다. |
'programming > Python' 카테고리의 다른 글
Python // 예외처리 (0) | 2017.12.07 |
---|---|
Python // 객체와 클래스 (0) | 2017.12.01 |
Python // 모듈과 패키지 (0) | 2017.11.30 |
Python // 함수 (0) | 2017.11.27 |
Python // 반복문 (0) | 2017.11.26 |