Python/2.7 information

전문가를 위한 파이썬 책에서 알아낸 것들..

qkqhxla1 2017. 7. 15. 19:22

유용할것 같은 것들 정리.


1. 리스트에서 인덱스로 엘리먼트를 가져오듯이, class에서 __getitem__을 구현해서 인덱스로 가져오게 할 수 있다. 

len등도 구현 가능하다. 더 찾아보면 많은게 있다. 앞에도 분명 이런글을 썼었던것 같은데... 사실 귀찮아서 안 찾아본듯 싶다.

class Deck:
	def __init__(self):
		self.cards = [chr(97+i) for i in xrange(10)]
	def __getitem__(self, index):
		return self.cards[index]
	def __len__(self):
		return len(self.cards)

deck = Deck()
print 'len = {}'.format(len(deck))
for i in xrange(10):
	print deck[i]

2. 튜플은 완벽한 불변이 아니다.

처음에 이거보고 되게 신기했다. 튜플 내부의 리스트에 5,6이 들어있는 리스트를 더하면 튜플 내부에 있는 값이니 안 변할까..? 아니면 그래도 리스트니 변할까? 굳이 답을 따지자면 답은 둘 다 맞다고 한다. 

try except문으로 오류가 발생하는지 테스트를 해놨는데  t[2] += [5,6]시 튜플에 값을 할당하려고 한다고 에러가 난다.

반면 t를 프린트해보면 5,6이 잘 할당되어 나온다. -_-?

내부 바이트코드 차이라는 말이 있는데 내부까지는 필요없을것 같고 그냥 이러면 안되겠구나.. 만 알아두자.

try:
	t = (1,2,[3,4])
	t[2] += [5,6]
except:
	print 'error!!'

print(t)

3. 해시 가능하다(hashable)는 말.

수명 주기동안 결코 변하지 않는 해시값을 갖고 있고(내부에 __hash__()메서드가 있어야 한다.), 다른 객체와 비교할 수 있으면(__eq__()메서드가 있어야 함) 객체를 해시 가능하다고 한다.

동일한 객체는 해시값이 동일해야 한다.

이것도 위처럼 튜플 안에 리스트가 들어있으면 해쉬어불한가...? 하는게 애매모호하다. 아래 테스트를 보자. 적당히 예상한 결과로 나온다.

def hashable_test(e):
	try:
		hash(e)
		return 'hashable'
	except:
		return 'unhashable'

a = (1,2)
print hashable_test(a)

a = (1,2,[5,6])
print hashable_test(a)

a = (1,2,frozenset([5,6]))
print hashable_test(a)

4. collections에 이런것도 있다.

https://docs.python.org/2/library/collections.html 한번 읽어보면 다른 신기한것들도 많다.

from collections import Counter, OrderedDict
ct = Counter('aaaaabbcececeaa')
print ct
ct.update('aaaccccc')
print ct
print ct.most_common(3)

5. 유니코드 관련.

전문가를 위한 파이썬 책의 유용한 파트 중 하나인것 같다. 에러가 뜰때마다 구글링 해보는것보다 책이 있다면 이 파트를 몇번 읽어보는것도 괜찮을것 같다.

아래는 2버전으로 돌려본건데... 3버전에선 당연히 결과가 다르게 나온다. 그냥 이런게 있다 정도만 알아두자.

# -*- coding: utf-8 -*-
cafe = u'cafè'
try:
	print cafe.encode('cp949') #cp949 인코딩이 에러가 남.
except:
	print 'error!'
#에러 처리 방법.
print cafe.encode('cp949', errors='ignore')
print cafe.encode('cp949', errors='replace')
print cafe.encode('cp949', errors='xmlcharrefreplace')
print


# 인코딩 방식 추측.
import chardet
import urllib2
page = urllib2.urlopen('https://www.naver.com/').read()
print chardet.detect(page)
print


#파이썬 2버전에서의 유니코드 파일 처리.
with open('cafe.txt', 'wb') as f:
	f.write(u'cafè'.encode('utf-8'))
with open('cafe.txt', 'rb') as f:
	print f.read().decode('cp949') # 당연히 utf-8로 인코딩하고 cp949로 디코딩하면 이상하게 나온다
print
#파이썬 3버전에서의 유니코드 파일 처리
#with open('cafe.txt', 'w', encoding='utf-8') as f:
#	f.write('~~~~~')


#유니코드 정규화 처리.
from unicodedata import normalize
#를 이용한다.


import unicodedata
import re
re_digit = re.compile(r'\d')
sample = u'1\xbc\xb2\u0969\u136b\u216b\u2466\u2480\u3285'
for char in sample:
	print 'U+%04x' % ord(char), u'{:<4}'.format(char),\
	're_dig' if re_digit.match(char) else '{:<6}'.format('-'),\
	'isdigit' if char.isdigit() else '{:<6}'.format('-'),\
	format(unicodedata.numeric(char), '5.2f'),\
	unicodedata.name(char)

추가 예정.