class 메소드 관련
Programming/Python 2013. 5. 8. 00:31 |실행 결과
실행 결과
'Programming > Python' 카테고리의 다른 글
발생자(Generator) (0) | 2013.05.09 |
---|---|
반복자(Iterator) (0) | 2013.05.09 |
협동적 메소드와 super() (0) | 2013.05.07 |
연산자 오버로딩 (0) | 2013.05.02 |
생성자와 소멸자 (0) | 2013.05.02 |
실행 결과
실행 결과
발생자(Generator) (0) | 2013.05.09 |
---|---|
반복자(Iterator) (0) | 2013.05.09 |
협동적 메소드와 super() (0) | 2013.05.07 |
연산자 오버로딩 (0) | 2013.05.02 |
생성자와 소멸자 (0) | 2013.05.02 |
협동적 클래스(Cooperative Classes) 란?
'협동적 super call'을 호출하는 다중 상속 관계에 있는 클래스들이다.
기존 클래스의 문제점
기존 클래스의 문제점을 살펴보자. 이것은 파이썬만의 문제가 아니라 대부분 객체지향 언어에서 발생할 수 있는 문제이다.
예를 들어, 어떤 클래스(A)가 주어져 있고, 서브 클래스(B)에서 슈퍼 클래스의 save 메소드를 확장하려 한다.
class A:
def save(self):
print 'A save call'
class B:
def save(self):
print 'B save call'
A.save(self)
A의 save는 A만의 자료를 저장하고 B의 save는 B만의 자료를 저장한다. 따라서 클래스 B의 save는 A.save 를 호출한다.
그러나 다이아몬드 관계인 경우 문제가 발생한다. 다음 클래스를 살펴보자.
이것을 수행하면 A의 데이터가 두 번이나 저장된다. (B에 의해 한 번, C에 의해 한 번)
위의 것을 현재 알고 있는 지식으로만 해결하면 다음과 같이 할 수 있겠다.
즉, 어떤 클래스의 save는 자신의 정보만을 저장하는 self._save()를 호출한 후에 슈퍼 클래스의 지역 정보를 저장하는 메소드를 일일이 호출해야 한다.
해결은 되었지만, 누가 봐도 좋은 코드라고 말할 수 없다. 클래스 D는 슈퍼 클래스들의 모든 구조를 알아야 save 메소드를 작성할 수 있다. 이러한 내용은 객체지향 언어가 추구하고 있는 방향과는 상반된 것이다.
또한 코드의 이식성이 크게 떨어지며 나중에 C를 제거하거나, 또 다른 클래스 E를 슈퍼 클래스로 추가하려면 D의 코드는 다시 작성되어야 한다.
협동적 클래스를 이용한 문제 해결
앞서와 같은 문제는 super를 이용한 협동적 클래스로 해결이 가능하다.
super()는 다음과 같은 형식을 가진다.
super(class name, self).method()
의미는 슈퍼 클래스의 '메소드'를 호출하라는 것이다. 슈퍼 클래스는 여러 개가 있을 수 있다. 따라서 어떤 슈퍼 클래스를 호출하는가는 self.__class__.__mro__ 와 '클래스 이름'을 이용하여 결정된다.
예를 들어, self.__class__.__mro__ 가 (w, x, y, z)이고 '클래스 이름'이 'x'일 경우 'x' 다음에 있는 'y'메소드가 호출된다.
구체적인 예)
클래스의 __mro__
super는 self.__class__.__mro__의 순서에 따라 save()를 호출한다고 했다. super는 self.__class__.__mro__에서 자신의 클래스 다음의 클래스 객체의 save를 호출한다.
예를 들어, super(C, self).save() 에서 전달된 self.__class__.__mro__가 (D, B, C, A, object) 라면, A.save(self) 를 호출한다.
단계적으로 설명:
1) d.save()에 의해서 super(D, self).save()가 호출된다. .self는 d이고 d.__class__.__mro__가 (D, B, C, A, object)이므로 super(D, self).save()에 의하여 B.save(self)가 호출된다.
2) B.save(self)에 의해서 super(B, self).save()가 호출된다. 이 때 self 는 여전히 'd' 임에 주의해야 한다. self.__class__.__mro__는 여전히 (D, B, C, A, object) 값을 가진다. 따라서, super(B, self).save()는 B 다음 클래스인 C 에서 C.save(self)를 호출한다.
3) 같은 방법으로 super(C, self).save()는 A.save(self)를 호출한다.
이와 같이 super를 사용하면 앞서 해결할 수 없었던 슈퍼 클래스 메소드의 호출 문제를 깔끔하게 해결할 수 있다.
클래스의 전체 구조를 모르고도 단지 '슈퍼 클래스의 이러한 메소드를 호출하라' 식의 표현으로도 충분히 잘 동작하는 코드를 작성할 수 있다.
반복자(Iterator) (0) | 2013.05.09 |
---|---|
class 메소드 관련 (0) | 2013.05.08 |
연산자 오버로딩 (0) | 2013.05.02 |
생성자와 소멸자 (0) | 2013.05.02 |
class member, instance member (0) | 2013.05.02 |
공백 문자 찾기
정규 표현식 검색을 수행할 때, 눈에 보이지 않지만 텍스트에 포함되는 공백 문자들도 찾아야 할 때가 있다.
예를 들어, 탭 문자를 모두 찾거나 줄바꿈 문자를 찾고 싶을 수도 있다. 꼼수를 이용하지 않고 이런 문자를 정규 표현식에 직접 써넣기가 어렵기 때문에, 아래와 같은 특수한 메타 문자들을 사용할 수 있다.
공백 메타 문자
메타 문자 |
설 명 |
[\b] |
백스페이스 |
\f |
페이지 넘김(form feed) |
\n |
줄 바꿈 |
\r |
캐리지 리턴 |
\t |
탭 |
\v |
수직 탭 |
ex) \r\n\r\n
\r\n은 줄 바꿈과 캐리지 리턴의 조합과 일치한다. 위도우에서 이 조합은 줄의 끝을 나타내는 데 사용한다.
따라서 \r\n\r\n 을 검색하면, 줄 끝이 연속해서 두 번 나오는 부분과 일치하는데, 이때 줄의 끝이 두 번 나온다는 것은 바로 두 레코드 사이에 빈 줄이 있음을 의미한다.
특정한 문자 형태와 일치시키기
문자 집합은 검색에서 쓰는 가장 흔한 형태이기에, 자주 쓰는 문자 집합들은 특수한 메타 문자로 대신하기도 한다.
이러 테마 문자들을 문자 클래스(classes of characters)라고 부른다. 직접 찾고 싶은 문자들을 열거하거나 범위를 사용하면 되기 때문에, 실제로 클래스 메타 문자를 써야만 하는 경우는 결코 없지만, 사용해 보면 너무나도 유용함을 알게 될 것이다.
다음은 거의 모든 정규 표현식 구현에서 기본으로 지원하는 클래스들이다.
숫자 메타 문자
메타 문자 |
설 명 |
\d |
숫자 하나([0-9])와 같다. |
\D |
숫자를 제외한 문자 하나([^0-9]와 같다) |
regex: myArray\[\d\+\]
※ 정규 표현 문법은 대소문자를 구별한다. \d는 숫자 하나와 일치하고, \D는\d와 뜻이 정반대다.
클래스 메타 문자에서도 소문자와 대문자는 서로 반대임을 뜻한다.
영숫자 문자와 영숫자가 아닌 문자 찾기
자주 사용하는 문자 집합이 또 있다. 영숫자(alphanumeric) 문자로, 대문자와 소문자를 포함한 알파벳 A부터 Z, 숫자, 밑줄을 포함한다.
대개 파일이나 디렉토리 이름, 애플리케이션 변수명, 데이터베이스 객체 이름 등에 사용한다.
영숫자 메타 문자
메타 문자 |
설 명 |
\w |
대소문자와 밑줄을 포함하는 모든 영숫자([a-zA-Z0-9_]와 같다) |
\W |
영수자나, 밑줄이 아닌 모든 문자(^a-zA-Z0-9_]와 같다) |
regex:
반복 찾기(+, *) 와 '?' 메타 문자 (0) | 2013.05.12 |
---|---|
포직스(POSIX) 문자 클래스 (0) | 2013.05.12 |
문자 집합으로 찾기 (0) | 2013.05.06 |
정규 표현식(Regualr Expression) (0) | 2013.05.05 |
태그 찾기 (0) | 2013.02.12 |
정규 표현식: [ns]a.\.
분석: 이 패턴은 n이나 s중 한 문자와 일치하며, c나 다른 문자와는 일치하지 않는다. 대괄호([ ])는 집합을 의미하기 때문에 대괄호 자체는 어떤 문자와도 일치하지 않는다. 대괄호([ ])는 집합을 의미하기 때문에 대괄호 자체는 어떤 문자와도 일치하지 않는다. 문자 a는 a와 일치하고 마침표(.)는 모든 문자와 일치한다.
※ 실제로 이런 상황에서 [ns]a.\. 는 정답이 아니다. 만약 파일명 가운데 usa1.xls가 있다면, 해당 파일명 역시 정규 표현식과 일치하기 때문이다.
이 문제를 해결하려면 위치도 지정해서 찾아야 한다.
위의 상황은 이것으로도 할 수 있다.
[ns]a[0-9]\.
※ 하이픈(-)은 대괄호([ ]) 안에서만 메타 문자인 특수한 메타 문자다.
집합 밖에서 하이픈(-)은 단순히 문자 그대로 하이픈(-)과 일치한다. 그래서 집합 밖에서는 하이픈(-) 문자에 굳이 역슬래시(\)를 붙일 필요가 없다.
제외하고 찾기
문자 집합은 일반적으로 찾고 싶은 문자의 목록을 정하는 데 쓰지만, 반대로 찾을 때 제외하고 싶은 문자 목록을 정할 때도 쓸 수 있다.
다른 말로, '여기서 지정한 목록을 제외하기' 라고 할 수 있다.
캐럿(^) 문자를 써 제외할 문자 집합을 지정한다.
캐럿(^)문자는 이 문자 바로 뒤에 있는 문자나 범위뿐만 아니라 집합 안에 있는 문자나 범위를 모두 제외한다.
regex: [ns]a[^0-9]\.
정리:
메타 문자인 대괄호([ ])는 문자 집합을 정의하는데, 그 집합 구성원 중에 한 문자라도 일치해야 한다.(and 가 아닌 or이다). 문자 집합은 문자를 일일이 열거하거나 하이픈(-)문자를 사용해 범위를 설정할 수 있다.
또 캐럿(^)문자는 지정한 문자들을 제외한 어떤 것들과 일치시킨다.
포직스(POSIX) 문자 클래스 (0) | 2013.05.12 |
---|---|
메타 문자 사용 (0) | 2013.05.06 |
정규 표현식(Regualr Expression) (0) | 2013.05.05 |
태그 찾기 (0) | 2013.02.12 |
[Python] Regular Expression (0) | 2013.02.07 |
정규 표현식(Regular Expression, 줄여서 레젝스(regex)라고도 한다)은 도구다.
그리고 다른 도구들과 마찬가지로 특정한 문제를 해결할 목적으로 만들어졌다 .
정규 표현식을 사용하는 이유는, 검색과 치환이 전부이다.
모든 정규 표현식은 일치하는 텍스트를 찾거나(검색) 텍스트를 찾은 뒤에 그것을 원하는 텍스트로 치환한다.(치환)
정규 표현식의 예)
정규 표현식 명령: .a.\.
마침표(.)는 한 문자와 일치한다.
역슬레시(\) 문자들이 문자 그대로 해석되게 한다(이스케이프). 특수한 문자 시퀀스를 시작하는 데 사용된다.
※ 마침표(.)는 모든 문자와 알치하지 않을 수 도있다. 하지만 대다수 정규 표현식 구현에서 마침표(.)는 줄바꿈(newline) 문자를 제외한 모든 문자와 일치한다.
메타 문자 사용 (0) | 2013.05.06 |
---|---|
문자 집합으로 찾기 (0) | 2013.05.06 |
태그 찾기 (0) | 2013.02.12 |
[Python] Regular Expression (0) | 2013.02.07 |
URL 교체하기 (0) | 2013.02.03 |
파이썬에서는 다른 자료형에 적용되는 모든 연산을 사용자가 정의하는 클래스에서 동작할 수 있도록 구현할 수 있다.
ex) 문자열 나누기
__div__ 메소드는 나누기 연산자 '/'가 사용되었을 때 자동으로 호출된다.
파이썬은 객체 m이 __div__ 메소드를 가지고 있는가를 동적으로 검사한다. 만일 메소드를 가지고 있다면 'b'를 인수로 __div__ 메소드를 호출한다.
즉, 다음과 같이 메소드를 호출한다.
# m / 'b' 와 같은 코드
m.__dive__('b')
만일 나눗셈의 피연산자 순서를 바꾸면 어떻게 될까?
예외가 발생한다.!! 객체가 오른쪽으로 가면, __rdiv__ 메소드를 호출하기 때문이다.
그래서 __rdiv__를 정의해야 한다.
예제에서는 __div__와 __rdiv__ 메소드 내부가 동일하다.
따라서, 다음과 같이 간단히 메소드를 정의할 수 있다.
__rdiv__ = __div__
수치 연산자 메소드
※ 피연산자가 바뀐 경우의 수치 연산자 메소드 이름앞에 'r' 만 추가해주면 된다.
ex) __rshift__ => __rrshift__
※ 확장 산술 연산자 메소드 (+=, -=, *= 등등...)
메소드 이름앞에 'i' 만 추가해주면 된다.
ex) __add__ => __iadd__
Method |
Operator |
__add__(self, other) | + |
__sub__(self, other) |
- |
__mul__(self, other) |
* |
__div__(self, other) |
/ |
__truediv__(self, other) |
from __future__ import division이 실행되었다면, '/' 연산자에 의해 이 메소드 호출 |
__floordiv__(self, other) |
// |
__mod__(self, other) |
% |
__divmod__(self, other) |
divmod() |
__pow__(self, other[, module]) |
pow(), ** |
__lshift__(self, other) 만 |
<< |
__rshift__(self, other) |
>> |
__and__(self, other) |
& |
__xor__(self, other) |
^ |
__or__(self, other) |
| |
수치 단항 연산자 메소드
Method |
Operator |
__neg__(self) |
- |
__pos__(self) |
+ |
__abs__(self) |
abs() |
__invert__(self) |
~ 비트 반전 (0은 1로, 1은 0으로) |
기타 형 변환 메소드
다음의 연산자들은 객체를 인수로 하여 함수 형태로 호출된다. 그에 따른 적절한 값을 리턴해 줘야 한다.
예를 들면, int(a) 에 의해서 a.int() 가 호출된다.
.__oct__, .__hex__ 인 경우는 문자열을 리턴한다.
Method |
Opereator |
__complex__(self) |
complex() |
__int__(self) |
int() |
__long__(self) |
long() |
__float__(self) |
float() |
__oct__(self) |
oct() |
__hex__(self) |
hex() |
class 메소드 관련 (0) | 2013.05.08 |
---|---|
협동적 메소드와 super() (0) | 2013.05.07 |
생성자와 소멸자 (0) | 2013.05.02 |
class member, instance member (0) | 2013.05.02 |
정적 메소드, 클래스 메소드, 장식자 (0) | 2013.05.01 |
일반적으로클래스는 생성자(constructor)와 소멸자(destructor)라 불리는 메소드를 정의할 수 있게 되어 있다.
생성자는 인스턴스 객체가 생성될 때 초기화를 위해서 자동적으로 불려지는 초기화 함수를 말하고,
소멸자는 인스턴스 객체가 사용이 끝나서 메모리에서 해제될 때 자원 해제를 위해서 자동으로 호출되는 함수를 말한다.
파이썬 클래스에서는 생성자와 소멸자를 위해 특별한 이름을 준비해 놓고 있다.
생성자 함수 이름은 __init__
소멸자 함수 이름은 __del__
※ 일반적으로 파이썬에서는 어떤 이름 앞뒤로 _(언더라인)이 두 개씩 붙어 있으면, 예약어(Reserved Words) 이다.
클래스 메소드로써는 미리 어떤 기능이 정의된 경우를 의미한다.
생성자는 대부분 인스턴스 멤버를 생성하고 값을 초기화하는 데 주로 사용된다.
소멸자는 실제로 많이 활용되지는 않는다. 왜냐하면, 대부분의 메모리나 기타 자원 관리가 자동으로 되기 때문에 특별히 신경 쓰지 않아도 인스턴스가 소멸하면서 자원이 원상 복귀되기 때문이다.
협동적 메소드와 super() (0) | 2013.05.07 |
---|---|
연산자 오버로딩 (0) | 2013.05.02 |
class member, instance member (0) | 2013.05.02 |
정적 메소드, 클래스 메소드, 장식자 (0) | 2013.05.01 |
메쏘드의 정의와 호출 (0) | 2013.05.01 |
멤버에는 두 가지가 있다. 클래스 멤버와 인스턴스 멤버이다.
클래스 멤버는 클래스 이름 공간에 생성된다.
클래스 멤버는 모든 인스턴스 객체들에 의해서 공유될 수 있다.
인스턴스 멤버는 인스턴스 객체 이름 공간에 생성된다.
인스턴스 멤버는 각각의 인스턴스 객체 내에서만 참조된다.
클래스 멤버는 메쏘드 바깥에 정의된다.
인스턴스 멤버는 메소드 내부에서 self를 이용하여 정의된다.
클래스 내부에서 멤버들을 참조할 때는 self.c_mem, self.i_mem 과 같이 한다.
외부에서 참조할 때...
클래스 멤버는 클래스이름.멤버이름 형식으로 호출하며, 인스턴스 멤버는 인스턴스이름.멤버이름 형식으로 호출한다.
클래스 멤버는 인스턴스이름.멤버이름 형식으로 호출하는 것이 가능하다.
단! 인스턴스 이름 공간에 같은 이름의 멤버가 없어야 한다. 인스턴스 이름 공간의 멤버를 우선적으로 처리하기 때문이다.
검색 순서
우선적으로 인스턴스 멤버를 참조한다.
만일, 인스턴스 멤버가 존재하지 않으면 클래스 멤버를 참조한다.
클래스 멤버는 모든 클래스 인스턴스가 공유하는 멤버이고,
인스턴스 멤버는 각각의 클래스 인스턴스가 별도로 가지고 있는 멤버이다. 즉, 각 인스턴스의 특성을 나타낸다고 할 수 있다.
연산자 오버로딩 (0) | 2013.05.02 |
---|---|
생성자와 소멸자 (0) | 2013.05.02 |
정적 메소드, 클래스 메소드, 장식자 (0) | 2013.05.01 |
메쏘드의 정의와 호출 (0) | 2013.05.01 |
class (0) | 2013.05.01 |