728x90
반응형

합성, 결합

composite pattern은 남의 클래스를 내가 가지고, 일을 함 

여러 instance를 하나의 명령어로 할 수 있고, 유지보수에 좋다.

또 이게 상속을 대신할 수 있음

잘안쓰는 것은 어려워서지 아예 안쓴다는 것이 아님

그래서 composite을 이용해서 상속을 대신하는 기법

 

내 클래스에 남의 instance를 가져올수있음

inheritance를 대신 씀, 활용 중 하나다

class A :
	pass
    
class C :
	pass

class B :
	def __init__(self) :
    	self.a = A()
		self.c = B();
        
	def multi(self) :
    	return self.a * self.b;
        # 이렇게 하면 상속

composite은 매우 밀접하게 연결짓는 것이라 유지보수면에서 힘든 면이 있다.

예를 들어 상속한 어미 클래스가 바뀌면 상속된 자식 클래스가 다 바뀌어버리는 경우가 있다.

 

그래서 느슨한 연결을 하는데 어떤 instance의 변수를 타 instance의 return 값으로 줘버리면

상속을 하지 않았지만 똑같이 만들 수 있다.

overiding 한다 하면

 

다른 composition 방식으로 __getattr__을 쓰면 된다.

만약 참조가 안되는 instance나 변수를 불러내면 attribute error가 나옴 

그런데 __getattr__를 쓰면 try : attribute error 로 받을 수 없는 값을 처리해줄 수 있다.

거기에 return getattr(다른 class)로 attributor를 이름으로, 지정된 값을 대신 불러다 줌

 

한편 _ 이름 규칙

1. 외부로 import 안됨, 내부 사용 

2. 국제화(internalization) 사용

3. name_이면 numpy 등 python과 충돌 방지용 

4. for i, _ in enumerate([1,2,3]) : 처럼 쓰지 않을 때 관례처럼

5. __name mangling private내부적으로 사용

6. _ : interactive last result : _이전의 마지막 out을 가져옴

7. __x__ : double underbar (dundu / magic method)

* sklearn은 __all__ = [a] *할 때 지정할 수 있음 => 사용자 편하라고 

혹은 __slot__으로 접근방지할 수있음

 

 

import sys

sys.path로 경로 순서대로 지정됨 확인 필요

 

 

getattribute => 아래와 같이 값이 있으면 값을 조작하는 것

setter 값을 선언 g.a = 1

getter 값을 봔환 g.a

deleter 값을 봔환 del g.a

 

'''

descriptor는 값을 사용못하게 하거나 숨기거나 할 때 사용

else [if else, for/while else, try]

from [import, raise, yield]

as [import, except, with]

import antigravity

import this

42

'''

# descriptor 만드는 3가지 방법

1. composite 방법

만들어진 class의 내용을 외부에서 조작할 수 있음

2. name = property(instance, instance) 지정할수있음

3. @property

@name.setter  / deleter로 지정할수있음

단순한 데이터를 처리할때는 = 로 할당할 수 있지만, =로 해야할게 많음

내부적으로 처리해야하는데 descriptor로 처리할 수 있다.

 

# meta class ★ class의 class

기능이 변경되면 meta class임

프레임워크 개발, 데이터를 조작할때 씀

class를 무제한으로 만들수있는데 1개의 instance만 만들수있게 class 기능 변경

type(1) => int

type(int) => type

meta class를 상속해서 meta class를 만듬

 

없으면 super().__call__()로 만들고, 있으면 기존의 instance를 return 해라 => 클래스의 기능을 변경함

class 지정해놓고 class 객체로 변수 선언하면 같은 값임

id()으로 확인하면 메모리 지정이 동일함

 

# abstract

공통된 규칙을 따르고 차이점만 새로 구현한다.

tensorflow가 a기능 제공하고 b,c 규칙을 따라야 한다하면

abstract 규칙을 공개해서 이거 따라야만 한다.

예를들어 from sklearn.naive_bayes import something이고

naive_bayes의 파생형들이 있다면, NB의 기본 규칙이 있고, 파생형들을 만들고 규칙을 공개하면 다른 사람들이 어디서든지 보고 따라할 수 있음 => 파생형이지만 쓰고 싶으면 행동의 규칙을 따라야 한다.

class ss(tf.keras.utils.sequence) :

     pass

dir(ss) => 동일한 기능이 나옴

print(inspect.getsource(기능))

=> abstractmethod있으면 규칙 따라야 함.

 

class A(metaclass = NBmeta) :

     @abstractmethod   => 제약 만듬

     def a(self) :            => 규칙

          pass

class B(A) :

     def a(self) :            => 규칙을 똑같이 만듬

         print('a')

b = B()  # notimplement error X

 

python에서도 이게 너무 어려우니깐 사람들 쓰라고 ABC쓰면 metaclass = 와 기능이 같음

ABC는 추상클래스이다.

 

 

# 상속 체계 확인

dir() 에 안보여도 metaclass, type안에 해봐서 mro를 쓸 수 있다.

.mro()

.__mro__

부모객체 확인 .__bases__

=> functional

마찬가지로 dir에서 확인할 수 없지만 metaclass에 정의되어있어서 가능 two track

 

# class 기능변경가능 => metaclass

# . descriptor

# 모든 연산자 기능 변경가능 => operator overloading

모든 연산자는 그에 대응하는 dundu(magic / special)가 있음

모든 연산자는 그에 대응하는 function이 있음 <- 함수형 프로그래밍 지원

3+4,

함수로하면 from operator import add, sub, mul

add(3, 4)

함수를 사용하는 이유는 인간은 연산자가 명확하지만 기능을 바뀔수가 있어 컴퓨터는 함수형이 의미를 명확하게 전달함

=> layers 도 함수형 연산함, 목적에 맞게 변형된 함수를 만들면 최적화에 좋다

 

 

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts