1. 클래스 속성과 인스턴스 속성
클래스 속성 : 클래스 자체에 바로 선언된 속성
인스턴스 속성 : 각 인스턴스별로 따로 가지고 있는 속성
클래스 속성은 한 클래스에서 나온 모든 인스턴스가 공유하고 있다.
즉,
class Person:
feeling = []
def got_feeling(self, feel):
Person.feeling.append(feel) #self.feeling.append(feel)와 같은 코드지만, 클래스 속성임을 조금 더 명시적으로 나타낸 것
alphaca = Person()
alphaca.got_feeling(‘nice’)
Beenzino = Person()
Beenzino.got_feeling(‘good’)
print(alphaca.feeling) #속성,메서드 이름을 찾는 순서는 인스턴스, 클래스 순.
print(Beenzino.feeling) #Beenzino의 속성을 호출한 것 같지만, 인스턴스 속성에 그 속성이 없으면 클래스 속성에서 해당 속성을 가져옴.
#결과
[‘nice’, ‘good’]
[‘nice’, ‘good’]
위와 같은 결과가 나온다.
같은 클래스에서 나온 인스턴스인 alphaca와 Beenzino는 클래스의 속성 feeling을 공유하므로, 어떤 인스턴스가 got_feeling()함수를 사용해 feeling에 요소를 추가했을 때, 나머지 인스턴스들도 모두 같은 feeling 리스트를 가지게된다.
이와는 달리 인스턴스 속성은 각각의 인스턴스 객체가 따로 가지고 있는 속성으로, 해당 인스턴스에서만 접근할 수 있다.
인스턴스 속성을 만드려면 생성자에서 인스턴스 속성을 명시해주면 된다.
def __init__(self):
self.feeling = []
2. 인스턴스 메서드와 정적메서드(static method)와 클래스메서드(class method)
인스턴스에서만 호출할 수 있는 일반적인 인스턴스 메서드와는 달리, 정적메서드와 클래스메서드는 클래스에서 바로 호출할 수 있다.
class 클래스명:
@staticmethod
def 메서드명(매개변수1, 매개변수2):
코드
정적메서드는 위와 같이 메서드 위에 @staticmethod라는 데코레이터를 붙여준다.
정적메서드는 매개변수로 self를 받지 않으므로 인스턴스에 접근할 수는 없다.
따라서 인스턴스 속성, 인스턴스 메서드를 쓰지 않고 클래스에서 바로 메서드를 쓰고싶을 때 사용한다.
단, 주의할 점은 정적 메서드가 클래스 자체에서만 사용할 수 있는 것은 아니라는 것이다. 인스턴스가 정적메서드를 사용할 수도 있다.
정적메서드는 인스턴스를 건드리지 않기 때문에 메서드를 사용하여도 외부상태에 영향을 끼치지 않는 순수 함수(pure function)을 만들 때 사용한다.
예를 들어 세트에 요소를 더하는 update()함수같은 경우 세트 인스턴스를 변화시키는 인스턴스메서드이지만, 두 집합을 조작하지 않고 합집합만을 반환해주는 union()함수는 인스턴스를 건드리지 않는 정적메서드이다.
이처럼 인스턴스를 변경시키고 싶을 때는 인스턴스 메서드, 인스턴스를 건드리지 않고 결과만 구하고 싶을 때는 정적메서드를 사용하면 된다.
클래스메서드도 정적메서드와 비슷하게 인스턴스 없이 호출할 수 있다.
class 클래스명:
@classmethod
def 메서드명(cls, 매개변수1, 매개변수2):
코드
위와 같이 선언하는 방식도 대부분 정적메서드와 비슷하지만, 차이점을 꼽자면 cls라는 매개변수가 하나 더 있다는 것을 알 수 있다.
cls는 현재 클래스를 전달하는 매개변수이다.
클래스메서드는 cls 인자를 전달받으므로 cls.속성명 처럼 클래스의 속성에 직접 접근할 수 있다. 이를 통해 클래스 속성에 접근하거나 해당클래스의 인스턴스를 만들 때 사용한다.
즉, 인스턴스와 클래스를 포함한 외부환경에 전혀 영향을 주지 않는 순수함수로서 기능하는 정적메서드와는 달리, 클래스의 속성이나 메서드에 접근하여 영향을 주기 위해 만들어진 것이 클래스메서드라고 볼 수 있다.
#정적메서드와 클래스메서드에 대해서는 나중에 파이썬 특성에 따로 정리
3. 클래스를 상속해야 할 때와 포함해야 할 때
클래스를 상속받은 자식클래스는 부모클래스의 속성과 메서드를 그대로 사용하면서 추가적으로 생성된 다른 속성과 메서드를 이용할 수 있다. 이처럼 클래스의 상속은 같은 종류의, 동등한 관계에 있는 클래스 간에 역할(기능)의 확장을 위해 사용한다.
그러나 특정 클래스가 다른 클래스를 포함할 때가 있다.
예를 들어
class Person:
def __init__(self):
print(“사람입니다”)
class PersonList:
def __init__(self):
self.person_list = [] #속성에 Person 인스턴스를 넣어서 관리
def append_person(self, person): #PersonList의 속성인 person_list에 Person클래스의 인스턴스를 추가하는 함수
self.person_list.append(person)
위와 같은 코드에서,
PersonList와 Person은 동등한 관계가 아니라 포함관계에 있다. (정확히 말하면, Person의 인스턴스들이 PersonList 인스턴스의 속성안에 리스트로 정리된다)
4. 추상클래스와 추상 메서드
클래스를 만들 때 특정 메서드는 반드시 구현하도록 강제하고싶을 때 추상클래스를 사용한다.
추상클래스는 상속에만 사용되는 클래스로, 해당 클래스 내에 추상메서드를 만들어놓는다. 그리고 그 추상 클래스를 상속받은 클래스에서는 추상메서드를 오버라이딩하여 반드시 해당 메서드를 구현해야한다. 그렇지 않으면 인스턴스로 생성할 수 없다.
추상클래스는 추상메서드의 구현을 강제하기 위해 만들어졌으므로 인스턴스를 만들 수없는 상속용 클래스이다.
추성클래스의 사용방법은 다음과 같다.
from abc import * #abstract base class에서 모든 함수를 가져오겠다
class 추상클래스명(metaclass=ABCmeta):
@abstractmethod
def 추상메서드명(self):
코드
일반적으로 추상메서드의 코드는 pass를 사용하여 비워두는데, 어차피 추상클래스로 인스턴스를 만들 수 없으므로 추상메서드도 다시 재정의하지 않는 이상 사용할 일이 없기 때문이다.
5. 이터레이터
이터레이터(iterator)는 값을 차례대로 꺼낼 수 있는 객체이다.
range같이 여러개의 값이 담긴 객체를 만들 때, 한번에 모든 값들을 만들어 놓으면 메모리낭비가 심하기때문에 값이 필요할때마다 값을 하나씩 만들어내는 이터레이터에서 꺼내서 사용한다. 이런 방식은 지연평가(lazy evalution)이라고 한다.
반복가능한 객체와 시퀀스, 이터레이터의 개념이 헷갈릴 수 있다.
반복가능한 객체 : 여러개의 요소가 있고 이를 하나씩 꺼낼 수 있는 객체를 일컫는다. ex - 리스트,튜플,문자열,세트, 딕셔너리, range 등
시퀀스 : 반복가능한 객체 중 요소의 순서가 정해져있고 연속적으로 이어져있는 객체이다. ex - 리스트, 튜플, 문자열, range 등
이터레이터 : 반복가능한 객체에서 __iter__메서드로 얻어지는 객체이며, 반복가능한 객체의 요소들을 하나씩 만들어내고 꺼내주는 역할을 한다.
즉, 반복가능한 객체의 부분집합 개념으로 시퀀스가 있다.
또, 이터레이터는 반복가능한 객체의 요소들을 한번에 하나씩 제공하기 위해 만들어진 도구같은 객체라고 볼 수 있다.
이터레이터는 언패킹이 가능하기때문에 여러개의 변수에 대한 할당이 가능하다. 물론 할당할 변수 개수와 넣을 요소 개수는 같아야한다.
일반적으로 자주 사용하는 map함수도 이터레이터의 일종이다. 그래서 리스트를 언패킹하여 여러 변수에 할당하는 것이 가능하다.
6. 제너레이터
제너레이터(generator)는 이터레이터를 생성해주는 함수이다.
이터레이터를 만들 때에는 클래스에 __init__, __next__, __getitem__이라는 함수를 구현해야하지만, 제너레이터 함수는 yield 키워드 하나로 이터레이터를 생성할 수 있다.
예시 식은 다음과 같다.
def number_generator():
yield 0
yield 1
yield 2
for i in number_generator():
print(i)
#결과
0
1
2
yield는 함수 바깥으로 값을 전달한다는 점에서 return과 같지만, 함수의 종료 측면에서 차이점이 있다.
return : 바깥으로 값을 반환하는 동시에 함수가 종료된다.
yield : 바깥으로 값을 전달하면서 대기상태로 돌입하였다가, 다음에 다시 next함수를 사용하면 다음 yield를 수행한다.
즉, yield를 사용하면 제너레이터 함수의 다음부분을 잠시 멈추고 코드실행을 바깥코드에 넘겨준다. 그러다가 바깥에서 next함수를 만나면 제너레이터로 돌아와 남은부분을 마저 수행하는 형식이다.
이는 일종의 코루틴(co-routine)으로, 함수를 사용할때 일반적으로 생성되는 서브루틴(sub-routine)과는 다른 수행방식이다.
파일 전체를 수행하고 있는 메인루틴에서 잠시 서브루틴으로 빠지는 방식이 아니라, 어떤 한 루틴이 수행되다가 수행 중간에 다른 루틴으로 차례를 넘겨주고, 그 루틴이 수행되다가 중간에 다시 다른 루틴으로 차례를 넘겨주는 방식을 취해서 코루틴이라고 부른다.
7. 정규표현식
정규표현식(regular expression)은 일정한 패턴을 가진 문자열을 표현하는 방식으로, 정규표현식을 이용해 방대한 텍스트에서 원하는 문자열 부분을 찾아내거나, 문자열이 정해진 패턴에 따라 작성되었는지 판단할 때 쓰인다.
정규표현식의 종류는 다음과 같다.
-문자열판단
^특문 : 문자열이 특문으로 시작하는가?
특문$ : 문자열이 특문으로 끝나는가?
특문1|특문2 : 문자열에 특문1이나 특문2 둘중 하나라도 있는가?
-개수판단
특문* : 특문이 0개이상 존재하는가?
특문+ : 특문이 1개이상 존재하는가?
특문? : 특문이 0개 또는 1개 존재하는가?
특문. : 특문이 있는 위치에 아무 문자(숫자)가 1개 있는가?
특문{개수} : 특문이 {개수}만큼 존재하는가?
(특문){개수} : 특문(문자열)이 개수만큼 존재하는가?
특문{시작개수,끝개수} : 특문이 최소 시작개수, 최대 끝개수만큼 존재하는가?
(특문){시작개수,끝개수} : 특문(문자열)이 최소 시작개수, 최대 끝개수만큼 존재하는가?
이떄 특문은 특정 문자열으로, a나 def같은 문자열뿐만 아니라 [0-9] —>숫자, [a-z] —> 영문소문자, [A-Z] —>영문대문자 같이 범위를 지정하여 사용할 수도 있다. 또, 특수문자의 경우에는 앞에 이스케이프문자(\)를 붙여주면된다.
만약 특정 문자범위에 포함이 되지 않는지를 알아보려면 아래와 같은 방식을 사용한다.
[^범위]* : 범위가 0개이상 있으면 가져오지 않음
[^범위]+ : 범위가 1개이상 있으면 가져오지 않음
이때 ^가 문자열의 시작을 판단할 때 사용되어서 헷갈릴 수 있는데, 대괄호 안에 존재하는 ^는 특정 범위를 제외한다는 의미이다.
위에 나타난 문자열들을 쉽게 나타내는 방식도 있다.
\d : [0-9]. 모든 숫자를 의미
\D : [^0-9]. 숫자를 제외한 모든 문자를 의미.
\w : [a-zA-Z0-9_]. 영문 대소문자, 숫자, 밑줄 문자를 의미
\W : [^a-zA-Z0-9_]. 영문 대소무자, 숫자, 밑줄 문자를 제외한 모든 문자를 의미.
----------------------------------------------------------
코딩도장 파이썬강의(https://dojang.io/course/view.php?id=7)에서 참조했습니다.
사용한 파이썬 버전은 3.8.1입니다.
'Always Awake > python 기본 정리(19.12.23~20.01.12)' 카테고리의 다른 글
20.01.09 정리 (0) | 2020.01.09 |
---|---|
20.01.06 정리 (0) | 2020.01.07 |
20.01.05 기록 (0) | 2020.01.06 |
19.12.26 기록 (0) | 2019.12.27 |
19.12.25 기록 (0) | 2019.12.26 |
댓글