Function
- encapsulation 캡슐화
Class
- 캡슐화를 해도 기본 접근 제한 없음 -> descriptor
Class 기본 용어
attribute : class 내부 모든 것
method : 클래스 안의 함수
class variable : 클래스 내의 변수
instance variable : 인스턴스 내의 변수
instance or object : class가 생성한 구체적인 값
class 작성
class A:
x = 1
def xx(self, t):
print(self, t)
Type과 Class의 관계
a = 1 #Literal
a = int(1) #객체지향 기본 방식
int도 class이지만 c의 영향을 받아 대문자가 아닌 소문자로 작성되어 있다.
다른 type도 마찬가지이다.
Class 변수
class A:
x = 1 #Class variable
Instance 변수
(1) class 생성 후 변수 정의
#instance variable
a1.t = 3
a2.t = 4
a3.t = 'a'
(2) class 내부에서 self에 변수 정의
class B:
def bb(self):
self.t = 1
b = B()
vars(b) #{}
b.bb()
vars(b) #{'t' : 1}
이때 instance 변수는 method가 실행 후 생성된다.
method가 실행된 모든 instance에 생성된다.
Class 변수와 Instance 변수의 차이
class A:
x = 1 #Class variable
a1 = A()
a2 = A()
a3 = A()
#instance variable
a1.t = 3
a2.t = 4
a3.t = 'a'
a1.x #1
a2.x #1
a3.x #1
vars(a1) {}
위 예제를 보면 class A의 instance a1, a2, a3는 모두 class 변수 x에 접근이 가능하다.
class 변수는 생성한 모든 instance에서 접근이 가능하다.vars
로 살펴보았을 때 인스턴스 a1에는 어떠한 변수도 정의되지 않은 것을 확인할 수 있다.
그렇다면 인스턴스에 같은 이름의 변수를 정의할 경우엔 어떻게 될까?
a3.x = 3
vars(a3) #{'x': 3}
a3 #3
a1 #1
인스턴스 local내에 같은 이름의 변수가 정의된 것을 확인할 수 있다.
따라서 a3.x는 local에 있는 변수의 값이 된다.
다른 인스턴스의 경우 global 값인 class 변수의 값이다.
init
__init__
정의
: __new__()
에 의해 인스턴스가 만들어진 후에, 호출자에게 돌려주기 전에 호출된다. 인스턴스를 커스터마이즈(초기화)한다.
class C:
def __init__(self):
self.t = 1
c = C()
vars(c) #{'t': 1}
metaclass
: class 역시 metaclass의 instance이다.따라서 instance화 하지 않고 class 자체로 사용이 가능하다.
class X:
def t(self, x):
self.x = x
def tt(self):
print(self.x)
X.t() #error
X.t(1) #error
X.t(1,1) #error
self
self
: instance를 가리키며, javascript에서의 this와 일맥상통한다.
class X:
def t(self, x):
self.x = x
def tt(self):
print(self.x)
#self 개념
a = X()
X.t(a, 3)
a.t #<function>
#self -> 공유하기 위해 생성되어 있음 (instance, class)
#a.t(a,3) -> a 중복되니 간편한 구문 위해 생략 -> error
###call
() 연산자의 세가지 사용
- func() => 함수실행
- class() => 인스턴스화
- instance() => call 정의된 class로 생성된 instance
class T:
def __init__(self):
self.a = 1
print('init')
t = T() #init
t() #callableerror
__call__
정의하지 않은 class의 instance는 callable하지 않다.
class T:
def __init__(self):
self.a = 1
print('init')
def __call__(self):
print('call')
tt = T() #init
tt() #call
T()() #init call
class도 함수처럼 사용 가능하다.
tensorflow에서는 __call__
대신 call
사용delegator
사용하여 call
로 바꿈
질문 (1) instance 변수로 call 정의해도 class변수처럼 작동할까?
namespace
def sin(self):
print('sin')
#다른 함수랑 이름이 겹쳐서 오버라이딩 될 수 있음
class Math:
def sin(self):
print('sin')
def cos(self):
print('cos')
#namespace로 사용
#instance로도 사용할 수 있는 문제 생김
scope 개념을 사용해서 namspace 생성한다.
Static method, 정적 메서드
: 함수이지만 클래스의 네임스페이스만 차용한 것. 인스턴스, self 없음.
(1) 기본 문법
class T:
@staticmethod
def ss():
print('static')
T.ss() #static
첫번째 인자로 self
가 들어가지 않았다.
(2) @staticmethod를 쓰지 않았을 때
class T2:
def ss():
print('static')
T2.ss() #static
t = T2()
t.ss() # self가 없어서 사용 불가
#Typeerror: T2.ss() missing 1 required positional argument: 'a'
@classmethod
class Y:
@classmethod
def z(cls):#self 대신 cls사용
cls.x = 1
print('cls')
Y.z() #cls
#instance 생성
yy = Y()
yy.z() #cls
yy.x #1
vars(yy) #{}
#LEGB , instance에 없는 method는 class에서 가져다 사용
self
대신 cls
사용한다.@
=> decorator
Single dispatch
하나의 메서드에서 arg의 타입에 따라 다른 행동을 보일 수 있다.
사용 방법
len({'a':1}) #1
#type에 따라 다르게 행동하지만 같은 함수 또는 메서드이다.
#list, dict 다른 결과
# => generic function
from functools import singledispatch
@singledispatch #arg가 한개라 single dispatch, 두개 이상은 multiple dispatch
def x(a):
print(a)
@x.register(int)
def _(a):
print('int')
@x.register(str)
def _(a):
print('str')
x(3.0) #3.0
x(3) #int
x('a') #str
Predicate(술어)
- 반환값이 보통 True, False이며, is나 callable이름을 가진 함수
예시
isinstance(3,int) #True
'고려대학교 지능정보 SW 아카데미 4기 > 정리노트' 카테고리의 다른 글
[Python] class의 __new__, __init__인자 에러 (0) | 2024.03.15 |
---|