import sys import weakref # weakref 모듈 임포트 class C: pass c = C() # 클래스 C의 인스턴스 생성 c.a = 1 # 인스턴스 c에 테스트용 값 설정 print sys.getrefcount(c) # 객체 c의 레퍼런스 카운트 조회 r = weakref.ref(c) # 약한 참조 객체 r 생성 print sys.getrefcount(c) # 객체 c의 레퍼런스 카운트 조회 --> 카운트 불변 d = c # 일반적인 레퍼런스 카운트 증가 방법 print sys.getrefcount(c) # 객체 c의 레퍼런스 카운트 조회 print print r # 약한 참조(weakref) 객체 print r() # 약한 참조로 부터 실제 객체를 참조하는 방법: 약한 참조 객체에 함수형태로 호출 print c print r().a # 약한 참조를 이용한 실제 객체 멤버 참조 print del c # 객체 제거 print sys.getrefcount(d) # 객체 d의 레퍼런스 카운트 조회 del d print r() # None을 리턴한다 print r().a # 속성도 참조할 수 없다 d = {'one': 1, 'two': 2} wd = weakref.ref(d) class Dict(dict): pass d = Dict({'one': 1, 'two': 2}) wd = weakref.ref(d) print wd print wd().keys() import sys import weakref class C: pass c = C() c.a = 2 print sys.getrefcount(c) # 객체 c의 레퍼런스 카운트 조회 p = weakref.proxy(c) #프록시 객체를 만든다 print sys.getrefcount(c) # 객체 c의 레퍼런스 카운트 조회 --> 카운트 불변 print print p print c print p.a import weakref class C: pass c = C() # 참조할 객체 생성 r = weakref.ref(c) # weakref 생성 p = weakref.proxy(c) # weakref 프록시 생성 print weakref.getweakrefcount(c) # weakref 개수 조회 print weakref.getweakrefs(c) # weakref 목록 조회 class C: pass c = C() c.a = 4 d = weakref.WeakValueDictionary() # WeakValueDictionary 객체 생성 print d d[1] = c # 실제 객체에 대한 약한 참조 아이템 생성 print d.items() # 사전 내용 확인 print d[1].a # 실제 객체의 속성 참조 del c # 실제 객체 삭제 print d.items() # 약한 사전에 해당 객체 아이템도 제거되어 있음 class C: pass c = C() c.a = 4 d = {} # 일반 사전 객체 생성 print d d[1] = c # 실제 객체에 대한 일반 참조 아이템 생성 print d.items() # 사전 내용 확인 print d[1].a # 실제 객체의 속성 참조 del c # 객체 삭제 (사전에 해당 객체의 레퍼런스가 있으므로 객체는 실제로 메모리 해제되지 않음) print d.items() # 일반 사전에 해당 객체 아이템이 여전히 남아 있음 d = weakref.WeakKeyDictionary() c = C() c.a = 4 d[c] = 1 # 실제 객체에 대한 약한 참조를 키로 지니는 아이템 생성 print d.items() del c # 실제 객체 삭제 print d.items() # 약한 사전에 해당 객체 아이템도 제거되어 있음 class Even: def __getitem__(self, k): return k * 2 e = Even() for x in e: # for ~ in 반복문으로 참조하는 경우, 자동으로 __getitem__(e, 0), __getitem__(e, 1), __getitem__(e, 2)... 등이 호출된다. print x, if x > 20: break print print e[2] # 단순 인덱싱으로 참조하는 경우 --> 이 경우 __getitem__(e, 2)가 호출된다. class Seq: def __init__(self, fname): # 읽을 파일 이름 설정 self.file = open(fname) def __getitem__(self, k): line = self.file.readline() # 한 라인을 읽는다. if not line: raise IndexError # 읽을 수 없으면 예외 발생 return line # 읽은 라인을 리턴한다. s = Seq('readme.txt') for line in s: # for ~ in 루프, 자동으로 __getitem__(s, 0), __getitem__(s, 1), __getitem__(s, 2)... 등이 호출된다. print line, S = Seq('readme.txt') print S[2] print S[4] I = iter([1,2,3]) print I print I.next() print I.next() print I.next() print I.next() def f(x): print x + 1 for x in [1,2,3]: f(x) def f(x): print x + 1 t = iter([1,2,3]) while 1: try: x = t.next() except StopIteration: break f(x) def f(x): print x + 1 t = iter([1,2,3]) for x in t: f(x) def f(x): print x + 1 for x in iter([1,2,3]): f(x) def f(x): print x + 1 for x in [1,2,3].__iter__(): f(x) def f(x): print x + 1 for x in (1,2,3).__iter__(): f(x) class Seq: def __init__(self, fname): self.file = open(fname) def __iter__(self): # iter(..)에 의해서 호출되는 메소드 return self # next 메소드를 구현하고 있으므로 self 자체가 반복자가 될 수 있다. def next(self): line = self.file.readline() # 한 라인을 읽는다. if not line: raise StopIteration # 읽을 수 없으면 예외 발생 return line # 읽은 라인을 리턴한다. s = Seq('readme.txt') # s 인스턴스가 next() 메소드를 지니고 있으므로 s 인스턴스 자체가 반복자임 for line in s: # 반복자 인스턴스에 대해서는 for ~ in 구문에 의하여 next() 메소드가 호출됨 print line, print print Seq('readme.txt') print list(Seq('readme.txt')) # list() 내장 함수가 객체를 인수로 받으면 해당 객체의 반복자를 얻어와 next()를 매번 호출하여 각 원소를 얻어온다. print tuple(Seq('readme.txt')) # tuple() 내장 함수가 객체를 인수로 받으면 해당 객체의 반복자를 얻어와 next()를 매번 호출하여 각 원소를 얻어온다. d = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5} for key in d: print key, d[key] d = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5} for key in d.__iter__(): print key, d[key] for key in d.iterkeys(): # 키에 대한 반복자, d.iterkeys() 가 반환한 반복자에 대해 next() 함수가 순차적으로 불리워짐 print key, keyset = d.iterkeys() print keyset.next() # 반복자 객체는 항상 next() 메소드를 지니고 있음 for key in keyset: # keyset 반복자에 대해 next() 메소드가 순차적으로 호출됨 print key, for value in d.itervalues(): # 값에 대한 반복자 print value, for key, value in d.iteritems(): #(키,값)에 대한 반복자 print key, value f = open('readme.txt') print "f.next()", f.next() for line in f: # f.next() 가 순차적으로 호출됨 print line, for line in iter(raw_input, ''): print line def accum(s, a): return s + a sum = 0 for sum in iter(lambda:accum(sum, 2), 40): print sum import math def accum(sum, a): return sum + a sum = 0 for sum in iter(lambda:accum(sum, math.pi), None): if sum >= 20: break print sum, from itertools import * L1 = [1,2,3] L2 = [4,5,6] for k in chain(L1, L2): print k, # L1, L2에 대해 연속된 데이터를 넘겨준다. print for k in (L1+L2): print k, #이 방법은 새로운 리스트를 생성하므로 메모리를 낭비한다. for k in count(10): if k == 100: break print k, i = 0 for k in cycle([1, 2, 3]): if i == 18: break print k, i += 1 names = ['gslee', 'kim', 'park'] for regNo, name in izip(count(140), names): #필요한 만큼 가져다쓴다. print regNo, name #for k in cycle([1,2,3]) #print k, for k in dropwhile(lambda x:x<3, [1,2,3,4,5,1,2]): print k, for k in takewhile(lambda x:x<3, [1,2,3,4,5,1,2]): print k, L = [(1,2), (2,3), (1,2), (4,2)] for key, group in groupby(sorted(L)): print key, list(group) from operator import itemgetter for key, group in groupby(sorted(L, key=itemgetter(1)), key=itemgetter(1)): print key, list(group) s = 'I like python I like programming' for key, group in groupby(sorted(s.split())): print key, len(list(group)) a = [1,2,3,4] b = [10, 20, 30, 40] dict(izip(a,b)) L = [(1,2), (2,3), (1,2), (4,2)] starmap(lambda x,y:x+y, L) #(1,2)가 x,y인수로 각각 전달된다. imap에서는 (1,2)가 한 개의 인수이다. list(ifilterfalse(lambda x:x%2, range(10))) L = [1,2,6,4,3,8,7,6] for ele in islice(L, 0, len(L), 2): print ele, L = [1,2,6,4,3,8,7,6] for k in repeat(L, 2): print k L = [(1,2), (2,3), (1,2), (4,2)] i1, i2 = tee(L) for k in i1: print k, print for k in i2: print k, def f(a,b): c = a * b d = a + b return c, d def generate_ints(N): for i in range(N): yield i gen = generate_ints(3) # 발생자 객체를 얻는다. generate_ints() 함수에 대한 초기 스택 프레임이 만들어지나 실행은 중단되어 있는 상태임 print gen print gen.next() # 발생자 객체는 반복자 인터페이스를 가진다. 발생자의 실행이 재개됨. yield에 의해 값 반환 후 다시 실행이 중단됨 print gen.next() # 발생자 실행 재개. yield에 의해 값 반환 후 다시 중단 print gen.next() # 발생자 실행 재개. yield에 의해 값 반환 후 다시 중단 print gen.next() # 발생자 실행 재개. yield에 의해 더 이상 반환할 값이 없다면 StopIteration 예외를 던짐 for i in generate_ints(5): print i, print [k for k in range(100) if k % 5 == 0] print (k for k in range(100) if k % 5 == 0) print sum((k for k in range(100) if k % 5 == 0)) del k print [k for k in range(100) if k % 5 == 0] print k # 외부에서 변수 참조가 가능하다 print del k print (k for k in range(100) if k % 5 == 0) print k # 발생자의 내부 변수는 참조할 수 없다 def fibonacci(a = 1, b = 1): while 1: yield a a, b = b, a + b t = fibonacci() # t는 발생자 for i in range(11): print t.next(), def fibonacci(a = 1, b = 1): while 1: yield a a, b = b, a + b for k in fibonacci(): # 발생자를 직접 for ~ in 구문에 활용 if k > 100: break print k, class Odds: def __init__(self, limit = None): # 생성자 정의 self.data = -1 # 초기 값 self.limit = limit # 한계 값 def __iter__(self): # Odds 객체의 반복자를 반환하는 특수 함수 return self def next(self): # 반복자의 필수 함수 self.data += 2 if self.limit and self.limit <= self.data: raise StopIteration return self.data for k in Odds(20): print k, print print list(Odds(20)) # list() 내장 함수가 객체를 인수로 받으면 해당 객체의 반복자를 얻어와 next()를 매번 호출하여 각 원소를 얻어온다. def odds(limit=None): k = 1 while not limit or limit >= k: yield k k += 2 for k in odds(20): print k, print print list(odds(20)) # list() 내장 함수가 발생자를 인수로 받으면 해당 발생자의 next()를 매번 호출하여 각 원소를 얻어온다. def alternating(a): ta = iter(a) # 우선 a를 반복자 객체로 변환한 후 while 1: ta.next() # 하나는 버리고 yield ta.next() #그 다음 것은 취하고 for x in alternating([1,2,3,4,5,6,7]): print x, def traverse(t): if not isinstance(t, list): return [t] res = [] for el in t: res.extend(traverse(el)) return res print traverse([1,2]) print print traverse([[1,2],3]) print a = [[1,2,3],4,5,[6,7],[8,9,10]] b = traverse(a) print b def traverse(t): for el in t: if isinstance(el, list): for k in traverse(el): yield k else: yield el print list(traverse([1,2])) print print list(traverse([[1,2],3])) print a = [1,2,3,[4,5],6,[7,[8,[9]],10]] b = list(traverse(a)) print b a = [1,2,3,[4,5],6,[7,[8,[9]],10]] print max(traverse(a)) print min(traverse(a)) print reduce(lambda x, y: x + y, traverse(a))