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 # 속성도 참조할 수 없다
2 2 3 <weakref at 0x10de07520; to 'instance' at 0x10de06a28> <__main__.C instance at 0x10de06a28> <__main__.C instance at 0x10de06a28> 1 2 None
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-23-5f79c52a60a5> in <module>() 22 del d 23 print r() # None을 리턴한다 ---> 24 print r().a # 속성도 참조할 수 없다 AttributeError: 'NoneType' object has no attribute 'a'
d = {'one': 1, 'two': 2}
wd = weakref.ref(d)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-7-b2a48d12fd2b> in <module>() 1 d = {'one': 1, 'two': 2} ----> 2 wd = weakref.ref(d) TypeError: cannot create weak reference to 'dict' object
class Dict(dict):
pass
d = Dict({'one': 1, 'two': 2})
wd = weakref.ref(d)
print wd
print wd().keys()
<weakref at 0x10ddda998; to 'Dict' at 0x10666f360> ['two', 'one']
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
2 2 <__main__.C instance at 0x10de023f8> <__main__.C instance at 0x10de023f8> 2
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 목록 조회
2 [<weakref at 0x10de07c58; to 'instance' at 0x10de06e60>, <weakproxy at 0x10de07ba8 to instance at 0x10de06e60>]
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() # 약한 사전에 해당 객체 아이템도 제거되어 있음
<WeakValueDictionary at 4527779424> [(1, <__main__.C instance at 0x10de06f38>)] 4 []
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() # 일반 사전에 해당 객체 아이템이 여전히 남아 있음
{} [(1, <__main__.C instance at 0x10de023f8>)] 4 [(1, <__main__.C instance at 0x10de023f8>)]
d = weakref.WeakKeyDictionary()
c = C()
c.a = 4
d[c] = 1 # 실제 객체에 대한 약한 참조를 키로 지니는 아이템 생성
print d.items()
del c # 실제 객체 삭제
print d.items() # 약한 사전에 해당 객체 아이템도 제거되어 있음
[(<__main__.C instance at 0x10de023f8>, 1)] []
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)가 호출된다.
0 2 4 6 8 10 12 14 16 18 20 22 4
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,
1: Hello World 2: Hello World 3: Hello World 4: Hello World 5: Hello World
S = Seq('readme.txt')
print S[2]
print S[4]
1: Hello World 2: Hello World
I = iter([1,2,3])
print I
print I.next()
print I.next()
print I.next()
print I.next()
<listiterator object at 0x102648cd0> 1 2 3
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-20-98af67aeb8bc> in <module>() 5 print I.next() 6 print I.next() ----> 7 print I.next() StopIteration:
def f(x):
print x + 1
for x in [1,2,3]:
f(x)
2 3 4
def f(x):
print x + 1
t = iter([1,2,3])
while 1:
try:
x = t.next()
except StopIteration:
break
f(x)
2 3 4
def f(x):
print x + 1
t = iter([1,2,3])
for x in t:
f(x)
2 3 4
def f(x):
print x + 1
for x in iter([1,2,3]):
f(x)
2 3 4
def f(x):
print x + 1
for x in [1,2,3].__iter__():
f(x)
2 3 4
def f(x):
print x + 1
for x in (1,2,3).__iter__():
f(x)
2 3 4
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()를 매번 호출하여 각 원소를 얻어온다.
1: Hello World 2: Hello World 3: Hello World 4: Hello World 5: Hello World <__main__.Seq instance at 0x10de0c6c8> ['1: Hello World\n', '2: Hello World\n', '3: Hello World\n', '4: Hello World\n', '5: Hello World'] ('1: Hello World\n', '2: Hello World\n', '3: Hello World\n', '4: Hello World\n', '5: Hello World')
d = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5}
for key in d:
print key, d[key]
four 4 three 3 five 5 two 2 one 1
d = {'one':1, 'two':2, 'three':3, 'four':4, 'five':5}
for key in d.__iter__():
print key, d[key]
four 4 three 3 five 5 two 2 one 1
for key in d.iterkeys(): # 키에 대한 반복자, d.iterkeys() 가 반환한 반복자에 대해 next() 함수가 순차적으로 불리워짐
print key,
four three five two one
keyset = d.iterkeys()
print keyset.next() # 반복자 객체는 항상 next() 메소드를 지니고 있음
for key in keyset: # keyset 반복자에 대해 next() 메소드가 순차적으로 호출됨
print key,
four three five two one
for value in d.itervalues(): # 값에 대한 반복자
print value,
4 3 5 2 1
for key, value in d.iteritems(): #(키,값)에 대한 반복자
print key, value
four 4 three 3 five 5 two 2 one 1
f = open('readme.txt')
print "f.next()", f.next()
for line in f: # f.next() 가 순차적으로 호출됨
print line,
f.next() 1: Hello World 2: Hello World 3: Hello World 4: Hello World 5: Hello World
far val in iter(callable, endval):
statements
for line in iter(raw_input, ''):
print line
aaa aaa bbb bbb ccc ccc
def accum(s, a):
return s + a
sum = 0
for sum in iter(lambda:accum(sum, 2), 40):
print sum
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
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,
3.14159265359 6.28318530718 9.42477796077 12.5663706144 15.7079632679 18.8495559215
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, #이 방법은 새로운 리스트를 생성하므로 메모리를 낭비한다.
1 2 3 4 5 6 1 2 3 4 5 6
for k in count(10):
if k == 100:
break
print k,
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
i = 0
for k in cycle([1, 2, 3]):
if i == 18:
break
print k,
i += 1
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
names = ['gslee', 'kim', 'park']
for regNo, name in izip(count(140), names): #필요한 만큼 가져다쓴다.
print regNo, name
140 gslee 141 kim 142 park
#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,
3 4 5 1 2
for k in takewhile(lambda x:x<3, [1,2,3,4,5,1,2]):
print k,
1 2
L = [(1,2), (2,3), (1,2), (4,2)]
for key, group in groupby(sorted(L)):
print key, list(group)
(1, 2) [(1, 2), (1, 2)] (2, 3) [(2, 3)] (4, 2) [(4, 2)]
from operator import itemgetter
for key, group in groupby(sorted(L, key=itemgetter(1)), key=itemgetter(1)):
print key, list(group)
2 [(1, 2), (1, 2), (4, 2)] 3 [(2, 3)]
s = 'I like python I like programming'
for key, group in groupby(sorted(s.split())):
print key, len(list(group))
I 2 like 2 programming 1 python 1
a = [1,2,3,4]
b = [10, 20, 30, 40]
dict(izip(a,b))
{1: 10, 2: 20, 3: 30, 4: 40}
L = [(1,2), (2,3), (1,2), (4,2)]
starmap(lambda x,y:x+y, L) #(1,2)가 x,y인수로 각각 전달된다. imap에서는 (1,2)가 한 개의 인수이다.
<itertools.starmap at 0x102599790>
list(ifilterfalse(lambda x:x%2, range(10)))
[0, 2, 4, 6, 8]
L = [1,2,6,4,3,8,7,6]
for ele in islice(L, 0, len(L), 2):
print ele,
1 6 3 7
L = [1,2,6,4,3,8,7,6]
for k in repeat(L, 2):
print k
[1, 2, 6, 4, 3, 8, 7, 6] [1, 2, 6, 4, 3, 8, 7, 6]
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,
(1, 2) (2, 3) (1, 2) (4, 2) (1, 2) (2, 3) (1, 2) (4, 2)
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 예외를 던짐
<generator object generate_ints at 0x10ddd6410> 0 1 2
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-8-65149ac25109> in <module>() 4 print gen.next() # 발생자 실행 재개. yield에 의해 값 반환 후 다시 중단 5 print gen.next() # 발생자 실행 재개. yield에 의해 값 반환 후 다시 중단 ----> 6 print gen.next() # 발생자 실행 재개. yield에 의해 더 이상 반환할 값이 없다면 StopIteration 예외를 던짐 StopIteration:
for i in generate_ints(5):
print i,
0 1 2 3 4
print [k for k in range(100) if k % 5 == 0]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
print (k for k in range(100) if k % 5 == 0)
<generator object <genexpr> at 0x10ddd64b0>
print sum((k for k in range(100) if k % 5 == 0))
950
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 # 발생자의 내부 변수는 참조할 수 없다
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95] 99 <generator object <genexpr> at 0x10ddd6780>
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-36-80e10688a4af> in <module>() 6 del k 7 print (k for k in range(100) if k % 5 == 0) ----> 8 print k # 발생자의 내부 변수는 참조할 수 없다 NameError: name 'k' is not defined
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(),
1 1 2 3 5 8 13 21 34 55 89
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,
1 1 2 3 5 8 13 21 34 55 89
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()를 매번 호출하여 각 원소를 얻어온다.
1 3 5 7 9 11 13 15 17 19 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
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()를 매번 호출하여 각 원소를 얻어온다.
1 3 5 7 9 11 13 15 17 19 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
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,
2 4 6
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
[1, 2] [1, 2, 3] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
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
[1, 2] [1, 2, 3] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
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))
10 1 55