자연어 처리 과제 중 [과제 1. "Data Preprocessing & Tokenization"]를 하면서 의문이었고, 찾아본 내용을 정리하였다.
파이썬 문법 적인 내용, 모듈에 대한 내용 등 여러 내용에 대해서 찾아보았고, 이렇게 기록하게 되었다.
전에도 ->(화살표)를 코드상에서 본 적이 있었는데, 이번에 제대로 찾아보았다.
python 3.6버전에 새로 추가된 변수 주석(syntax for variable annotations)라는 새 기능을 이제야 알게 되었다. annotation을 통해 함수나 변수 등에 미리 타입에 대한 힌트를 적어둘 수 있다. 물론, 파이썬에서 강제성이 있거나, 지켜야 한다는 것은 아니다. annotation은 말 그대로 '힌트'를 주는 것에 불과하다.
약간 이런 것이다.
class AnnotationClassExample:
""" Annotation에 대한 예시를 확인하기 위한 class입니다.
__annotation__ 속성을 통해 class할당되는 first_param과
second_param에 대한 타입을 확인할 수 있습니다. """
first_param: str
second_param: int
def set_first_param(self, value: str) -> None:
"""
AnnotationClassExample 클래스의 first_param 값을 바인딩합니다.
함수의 반환은 없습니다.
"""
self.first_param = value
def set_second_param(self, value: int) -> bool:
"""
AnnotationClassExample 클래스의 second_param 값을 바인딩합니다.
함수의 반환은 True or False 입니다.
"""
if type(value) == int:
self.second_param = value
return True
else:
self.second_param = 0
return False
def main():
print("Annotation 만들어보기")
new_class = AnnotationClassExample()
print("\n* AnnotationClassExample 클래스의 annotations")
print(new_class.__annotations__)
print("\n* set_first_param 함수의 annotations")
print(new_class.set_first_param.__annotations__)
print("\n* set_second_param 함수의 annotations")
print(new_class.set_second_param.__annotations__)
if __name__ == '__main__': main()]
이렇게 annotation을 적용하면, 그 개체에 대해 annotations 이라는 속성이 생긴다. 그리고 해당 속성을 통해 우리가 적용해둔 annotation 값을 볼 수 있는 것이다.실제로 위의 코드를 실행시켜 보면 main함수내에서 각 클래스와 함수에 대해 annotations 속성을 호출하고, 그 결과는 다음과 같다.
def push(self, x: int) -> None:
self.queue.append(x)
python3에서는 함수 정의시 나타나는 화살표(->)는 함수 리턴 값의 주석 역할을 한다.
말그대로 주석이기 때문에 있으면 좋지만 없다고 문제가 되지는 않는다.
위 함수에서는 None 타입을 리턴하는 함수다.
비슷한 역할로 변수에 대한 주석 역할을 하는 콜론이 있다. 위 코드를 보면 x: int 라는 표현이 있는데, 이는 매개변수 x 타입에 대한 주석이다. 즉 x 값은 int로 들어올 것이다. 라는 의미다. 마찬가지로 주석이기 때문에 없다고 문제가 되지는 않는다.
name: str = 'Mike'
이 코드는 사실 주석을 띄고 보면,
name = 'Mike' 로 변수가 선언되는 거다.
이 과정에서 :str 부분을 추가해서, 즉 name 변수 뒤에 콜론을 붙여, str 형이라는 것을 주석으로 알려주고 있는 것이다.
def tokenize(sentence: str) -> List[str]:
print(sentence)
...생략...
위의 코드에서는 말그대로, tokenize 함수에 인자로 sentence가 있는데 그 자료형은 str이라는 hint를 주는 것이고, tokenize 라는 함수의 결과 값은 list라고 리턴 값을 주석으로 표현해주고 있다.
target = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = filter(lambda x : x%2==0, target)
print(list(result))
# 출력결과 : [2, 4, 6, 8, 10]
별표 문법(asterisk/star syntax)으로 각 리스트를 풀고 그것들을 chain()에 몽땅 집어 넣었더니 싹 다 붙었다. 간단(simple)하고 간소(compact)한 것 말고도 장점이 있는데, 리스트에 들어 있는 리스트가 많거나 적어져도 코드에 손댈 필요가 없다는 점이다. 확장적인(scalable) 구현이 가능하다!
get(x) 함수는 x라는 Key에 대응되는 Value를 리턴한다.
>>> a = {'name': 'pey', 'phone': '010-9999-1234', 'birth': '1118'}
>>> a.get('name')
'pey'
>>> a.get('phone')
'010-9999-1234'
딕셔너리에 존재하지 않는 키로 값을 가져오려고 할 경우, a['nokey'] 방식은 오류를 발생시키고 a.get('nokey') 방식은 None을 리턴한다는 차이가 있다.
>>> a = {'name':'pey', 'phone':'010-9999-1234', 'birth': '1118'}
>>> print(a.get('nokey'))
None
>>> print(a['nokey’])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'nokey'
딕셔너리 안에 찾으려는 Key가 없을 경우, 미리 정해 둔 디폴트 값을 대신 가져오게 하고 싶을 때는 get(x, '디폴트 값')을 사용할 수 있다.
>>> a.get('nokey', 'foo')
'foo'
과제 중 있었던 아래의 코드를 보고 정규표현식을 다시 한 번 정리했다.
tokens = list(filter(lambda x: x, re.split(r'\s+|([.,!?]|n\'t|\'\w+)', sentence.lower())))
[ ]
문자(문자 클래스) : 문자 클래스를 만드는 메타 문자인 [ ] 사이에는 어떤 문자도 들어갈 수 있다. 즉, 정규 표현식이 [abc]라면 이 표현식의 의미는 ‘a, b, c 중 한 개의 문자와 매치’를 뜻한다.\d
: 숫자와 매치된다. [0-9]와 동일한 표현식이다.\D
: 숫자가 아닌 것과 매치된다. [^0-9]와 동일한 표현식이다.\s
: 화이트스페이스(whitespace) 문자와 매치된다. [ \t\n\r\f\v]와 동일한 표현식이다. 맨 앞의 빈칸은 공백 문자(space)를 의미한다.\S
: 화이트스페이스 문자가 아닌 것과 매치된다. [^ \t\n\r\f\v]와 동일한 표현식이다.\w
: 문자+숫자(alphanumeric)와 매치된다. [a-zA-Z0-9_]와 동일한 표현식이다.\W
: 문자+숫자(alphanumeric)가 아닌 문자와 매치된다. [^a-zA-Z0-9_]와 동일한 표현식이다.|
- | 메타 문자는 or과 동일한 의미로 사용된다. A|B라는 정규식이 있다면 A 또는 B라는 의미가 된다.>>> p = re.compile('Crow|Servo')
>>> m = p.match('CrowHello')
>>> print(m)
<re.Match object; span=(0, 4), match='Crow'>
🔖 Reference
New in Python: Syntax for variable annotations
python annotation
내장함수 re
wikidocs_re
내장모듈 itertools