• Source
    1. # -*- coding: utf-8 -*-
    2. # q1011_answer_2.py
    3.  
    4. # 使用した Python のバージョン:
    5. # ・Python(Python 2.7.3)/Python3(Python 3.2.3)
    6. # 工夫した点・苦労した点・感想等(ご自由にお書きください):
    7. # ・インスタンス変数 _cache を導入し、オリジナルの it の生成結果を保持するようにしました。
    8.  
    9. # 必要に応じてここに import 文を挿入してもOKです。
    10. # 例:import itertools
    11.  
    12. class IteratorCloner:
    13. def __init__(self, it):
    14. self._it = iter(it)
    15. self._cache = []
    16.  
    17. def get_clone(self):
    18. index = 0
    19. while True:
    20. if len(self._cache) <= index:
    21. next_val = next(self._it)
    22. self._cache.append(next_val)
    23. yield self._cache[index]
    24. index += 1
    25.  
    26. # ※これ以降は変更しないこと。
    27. if __name__ == '__main__':
    28. import unittest
    29. import random
    30. from itertools import islice, takewhile
    31.  
    32. def rand_enum():
    33. while True:
    34. # 1〜20の整数値をランダムに列挙
    35. yield random.randint(1, 20)
    36.  
    37. def fib():
    38. a, b = 0, 1
    39. while True:
    40. yield b
    41. a, b = b, a + b
    42.  
    43. def take_10(it):
    44. return list(islice(it, 10))
    45.  
    46. def take_under_100(it):
    47. return list(takewhile(lambda n: n < 100, it))
    48.  
    49. class IteratorClonerTest(unittest.TestCase):
    50. def setUp(self):
    51. self.cloner = IteratorCloner(fib())
    52.  
    53. def test_fib_clone1(self):
    54. fib = self.cloner.get_clone()
    55. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    56. result = take_under_100(fib)
    57. self.assertEqual(result, expected)
    58.  
    59. def test_fib_clone2(self):
    60. fib1 = self.cloner.get_clone()
    61. fib2 = self.cloner.get_clone()
    62. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    63. result1 = take_10(fib1) # dispose
    64. result2 = take_under_100(fib2)
    65. self.assertEqual(result2, expected)
    66.  
    67. def test_fib_cloneN(self):
    68. expected = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    69. result = None
    70. # 3回以上10回以下のランダム回数繰り返す
    71. for i in range(random.randint(3, 10)):
    72. result = take_under_100(self.cloner.get_clone())
    73. self.assertEqual(result, expected)
    74.  
    75. def test_rand_enum(self):
    76. cloner = IteratorCloner(rand_enum())
    77. expected = take_10(cloner.get_clone())
    78. result = take_10(cloner.get_clone())
    79. self.assertEqual(result, expected)
    80.  
    81. # run tests
    82. unittest.main()
    83.