ทีนี้เขียนไปเขียนมารู้สึกว่า code มันไม่สวยเอาซะเลย เพราะไอ้จำนวนเหล่านี้เนี่ย เวลาหามันจะกระโดดข้ามไป index ที่ต้องการไม่ได้อยู่แล้ว บวกกับจำนวนพวกนี้มันหาเพิ่มได้เรื่อยๆ ไม่มีที่สิ้นสุด ดังนั้นในสายตาของนักคณิตศาสตร์อย่างผม ถ้าเขียน
prime[100]
แล้วเจอฟ้องว่า index out of range
นี่คงเซ็งน่าดู เลยคิดว่ามันน่าจะมีวิธี hack ให้ใช้ syntax นี้หาค่าใน index ที่ต้องการแม้ต้อนนี้จะยังไม่มีได้ค้นไปค้นมาก็เจอ
list.__getitem__
เลยจัดการลงมือลุยclass InfinityList(list): def __iter__(self): n = 0 while True: yield self[n] n += 1 def __repr__(self): return super(InfinityList, self).__repr__()[:-1] + ', ...]' class fibonacci(InfinityList): def __getitem__(self, n): while True: try: return super(InfinityList, self).__getitem__(n) except IndexError: self.append( super(InfinityList, self).__getitem__(-1) + super(InfinityList, self).__getitem__(-2) ) def __init__(self): super(InfinityList, self).__init__([1, 1]) class prime(InfinityList): def __getitem__(self, n): while True: try: return super(InfinityList, self).__getitem__(n) except IndexError: c = super(InfinityList, self).__getitem__(-1) while True: c += 2 for p in self[:]: if not c % p: break else: self.append(c) break def __init__(self): super(InfinityList, self).__init__([2, 3]) fibonacci = fibonacci() prime = prime()กรอเวลาไปข้างหน้า 8 ชั่วโมง ก็มีของเล่นใหม่ตามที่แปะเป็นตัวอย่างไว้ด้านบน
- ใน
__getitem__
นี่ลืมไปว่าถ้าแก้ตรงนี้แล้วมันจะทำ recursion กับตัวเอง ทำให้ไม่สามารถใช้ syntax อย่างfibonacci[-1]
เพื่อดึงเอาตัวเลขออกมาได้ ก็เลยต้องเลี่ยงไปเรียก method จาก super class เอา - จะให้ syntax แบบ
list[n]
ทำงานโดยเรียก__getitem__
ต้อง inherit class มาแล้ว define ไว้ตอนสร้าง class เท่านั้นด้วย มาสั่งclass.__getitem__ = outer_function
ไม่ได้ (ป้องกัน injection เข้าระบบ) - ตัว
__getitem__
มันรับ parameter ได้อันเดียวก็จริง แต่ไม่ใช่แค่ตัวเลขเท่านั้น เพราะยังมี slice object อีกด้วย (นึกถึงเวลาเขียนsome_list[4:-4]
ไอ้[4:-4]
นั่นแหละ slice object) ดังนั้นงานนี้ play safe ใส่while True
ไปดีกว่า ช้าหน่อยยอมรับได้ - สุดท้ายก็คืออยากให้ class พวกนี้เป็น static ไปซะ (ตอนแรกออกแบบว่าจะให้เขียนเป็น
prime.numbers[n]
ด้วยซ้ำ) แต่เหนื่อยมากขี้เกียจทำแล้ว เลยจับประกาศชื่อ fibonacci, prime ทับกับชื่อ class ตัวมันเองไปซะเลย ยังไงก็มีได้แค่ instance เดียวอยู่แล้วหนิ 555+
prime[100]จบเลย ง่ายมั้ย? อยากลองเล่นเองแล้ว? ไปจิ้ม code ได้จากที่นี่เลย XD
No comments:
Post a Comment