มีนิพจน์สำหรับเครื่องกำเนิดไฟฟ้าที่ไม่สิ้นสุดหรือไม่?


119

มีนิพจน์เครื่องกำเนิดไฟฟ้าแบบตรงไปตรงมาที่สามารถให้องค์ประกอบที่ไม่มีที่สิ้นสุดหรือไม่?

นี่เป็นคำถามเชิงทฤษฎีล้วนๆ ไม่จำเป็นต้องมีคำตอบที่ "ใช้ได้จริง" ที่นี่ :)


ตัวอย่างเช่นการสร้างเครื่องกำเนิดไฟฟ้าที่ จำกัด เป็นเรื่องง่าย:

my_gen = (0 for i in xrange(42))

อย่างไรก็ตามในการสร้างสิ่งที่ไม่มีที่สิ้นสุดฉันต้อง "สร้างมลพิษ" เนมสเปซของฉันด้วยฟังก์ชันปลอม:

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

การทำสิ่งต่างๆในไฟล์แยกกันและการทำในimportภายหลังจะไม่นับรวม


ฉันยังรู้ว่าitertools.repeatมันทำอย่างนี้ ฉันอยากรู้ว่ามีวิธีแก้ปัญหาแบบซับเดียวหรือไม่


9
คุณไม่จำเป็นต้องจริงที่จะก่อให้เกิดมลพิษ namespace ของคุณ ... เพียงแค่ชื่อฟังก์ชั่นแล้วทำmy_gen my_gen = my_gen()
6502

2
คุณสามารถใช้del _my_genถ้าคุณไม่ต้องการสร้างความสับสนให้กับทั้งสองอย่าง
John La Rooy

คำตอบ:


133
for x in iter(int, 1): pass
  • สองอาร์กิวเมนต์iter= เป็นศูนย์อาร์กิวเมนต์ callable + ค่า sentinel
  • int() กลับมาเสมอ 0

ดังนั้นจึงiter(int, 1)เป็นตัววนซ้ำที่ไม่มีที่สิ้นสุด เห็นได้ชัดว่ามีรูปแบบต่างๆมากมายในชุดรูปแบบนี้ (โดยเฉพาะเมื่อคุณเพิ่มlambdaลงในส่วนผสม) หมายเหตุที่แตกต่างกันอย่างหนึ่งคือการiter(f, object())ใช้อ็อบเจ็กต์ที่สร้างขึ้นใหม่เนื่องจากค่า sentinel เกือบจะรับประกันตัววนซ้ำที่ไม่มีที่สิ้นสุดโดยไม่คำนึงถึง callable ที่ใช้เป็นอาร์กิวเมนต์แรก


3
วิธีที่น่าสนใจมากในการใช้iterกับทรัพย์สินintที่หลายครั้งเราลืม
Senthil Kumaran

3
คุณสามารถใช้สูตรวิเศษนี้เพื่อจำลองitertools.count:count = lambda start=0, step=1: (start + i*step for i, _ in enumerate(iter(int, 1)))
Coffee_Table

1
เพียงเพื่ออธิบายสิ่งที่เกิดขึ้นที่นี่: เมื่อฟังก์ชั่เรียกว่ามีสองข้อโต้แย้งมันจะทำงานแตกต่างกันเล็กน้อยกว่าปกติ:iter iter(callable, sentinel) -> iteratorอาร์กิวเมนต์ 1 callableถูกเรียกสำหรับการวนซ้ำของตัววนซ้ำจนกว่าจะส่งคืนค่าของsentinel. อย่างไรก็ตามในขณะที่int()มักจะกลับ0เราสามารถเรียกint()ตลอดไปและไม่เคยไปถึง 1. พระทัยในผลกระทบนี้จะผลิตรายการที่ไม่มีที่สิ้นสุดของ0's
Olsgaard

217

itertools ให้เครื่องกำเนิดไฟฟ้าสามเครื่องที่ไม่มีที่สิ้นสุด:

ฉันไม่รู้จักคนอื่น ๆ ในไลบรารีมาตรฐาน


เนื่องจากคุณขอซับเดียว:

__import__("itertools").count()

18
Re: repeat (x, times = ∞) - ไม่มีสัญลักษณ์สำหรับใครก็ตามที่สงสัย - การละเว้นอาร์กิวเมนต์ทำให้การทำงานซ้ำตลอดไป
Mr_and_Mrs_D

โหวตขึ้นเนื่องจาก (ในขณะที่คำตอบของ ncoghlan จะตอบคำถามของ OP โดยตรง) สิ่งนี้ใช้ได้โดยทั่วไปมากกว่า
Huw Walters

นี่เป็นสิ่งที่อ่านได้ง่ายกว่าiter(int, 1)คาถา เสียดายitertoolsไม่มีendlessly()วิธีการที่มีจุดประสงค์เดียวคือทำเช่นนี้ itertools.count()ไม่ใช่ทั้งหมดที่อ่านได้
BallpointBen

19

คุณสามารถทำซ้ำบน callable ที่ส่งคืนค่าคงที่ต่างจากแมวมองของ iter () เสมอ

g1=iter(lambda:0, 1)

8
ฉันทั้งรักและเกลียดสิ่งนี้ ... ฉันชอบที่มันบรรลุสิ่งที่ฉันต้องการในตัวละครไม่กี่ตัว แต่เกลียดที่ไม่มีใครมองมันและรู้ว่ามันควรจะทำอย่างไร
ArtOfWarfare

1
การรู้ไวยากรณ์ของiter(ที่นี่พร้อมกับ sentinel พิเศษ) และไวยากรณ์ของlambda(ที่นี่โดยไม่มีพารามิเตอร์ใด ๆ ที่ส่งผ่านเพียงreturn 0) สถานที่เดียวที่จะเกลียดคือปริศนาg1นั้น
Sławomir Lenart

ผู้ชายไม่เคยได้รับมัน มันเล็กจนน่าตกใจดังนั้นฉันจึงฉีด 1g
user237419

8

ระบบปฏิบัติการของคุณอาจมีบางสิ่งที่สามารถใช้เป็นเครื่องกำเนิดไฟฟ้าที่ไม่มีที่สิ้นสุด เช่นบน linux

for i in (0 for x in open('/dev/urandom')):
    print i

เห็นได้ชัดว่าสิ่งนี้ไม่ได้มีประสิทธิภาพเท่ากับ

for i in __import__('itertools').repeat(0)
    print i

11
โซลูชัน / dev / urandom ขึ้นอยู่กับ\ns ที่ปรากฏเป็นครั้งคราว ... คดโกง! :)
hugomg

5

ไม่มีที่ไม่ใช้ตัววนซ้ำแบบไม่มีที่สิ้นสุดภายในที่กำหนดให้เป็นคลาส / ฟังก์ชัน / ตัวสร้าง (ไม่ใช่ - นิพจน์ฟังก์ชันที่มีyield) นิพจน์ตัวสร้างจะดึงมาจาก anoter ที่ทำซ้ำได้เสมอและไม่ทำอะไรเลยนอกจากการกรองและแมปไอเท็ม คุณไม่สามารถเปลี่ยนจากรายการที่ จำกัด ไปเป็นรายการที่ไม่มีที่สิ้นสุดโดยมีเพียงmapและfilterคุณต้องการwhile(หรือสิ่งforที่ไม่ยุติซึ่งเป็นสิ่งที่เราไม่สามารถทำได้โดยใช้เพียงอย่างเดียวforและการวนซ้ำแบบ จำกัด )

เรื่องไม่สำคัญ: PEP 3142มีความคล้ายคลึงกันอย่างผิวเผิน แต่เมื่อตรวจสอบอย่างใกล้ชิดดูเหมือนว่ายังคงต้องใช้forข้อ (ดังนั้นจึงไม่ใช่(0 while True)สำหรับคุณ) กล่าวคือให้ทางลัดสำหรับitertools.takewhile.


ตามที่ฉันสงสัย ... เราแน่ใจได้หรือไม่ว่าไม่มีเครื่องกำเนิดไฟฟ้าที่ไม่มีที่สิ้นสุดที่พร้อมจะใช้ในทางที่ผิด? (น่าเศร้าที่ xrange (0,1, -1) ไม่ทำงาน ... )
hugomg

2
@missingno: from itertools import repeat, count, cycleอาจนับได้ว่า "พร้อมใช้งาน" สำหรับคนส่วนใหญ่
ncoghlan

1
โอ๊ะฉันลืมประมาณ iter2 ตัวทำซ้ำที่ไม่มีที่สิ้นสุดมีให้บริการในตัว - ดูคำตอบของฉัน :)
ncoghlan

5

ค่อนข้างน่าเกลียดและบ้าคลั่ง (แต่ตลกมาก) แต่คุณสามารถสร้างตัววนซ้ำของคุณเองจากนิพจน์ได้โดยใช้เทคนิคบางอย่าง (โดยไม่ต้อง "สร้างมลพิษ" เนมสเปซของคุณตามต้องการ):

{ print("Hello world") for _ in
    (lambda o: setattr(o, '__iter__', lambda x:x)
            or setattr(o, '__next__', lambda x:True)
            or o)
    (type("EvilIterator", (object,), {}))() } 

คุณรัก LISP อย่างชัดเจน
Faissaloo

1
@Faissaloo อันที่จริง ... คุณอาจพบว่ามีการแสดงออกที่บ้ากว่าในหน้าเก่าที่ฉันเขียน: baruchel.github.io/python/2018/06/20/…
Thomas Baruchel

2

บางทีคุณอาจใช้มัณฑนากรเช่นนี้:

def generator(first):
    def wrap(func):
        def seq():
            x = first
            while True:
                yield x
                x = func(x)
        return seq
    return wrap

การใช้งาน (1):

@generator(0)
def blah(x):
    return x + 1

for i in blah():
    print i

การใช้งาน (2)

for i in generator(0)(lambda x: x + 1)():
    print i

ฉันคิดว่าควรปรับปรุงเพิ่มเติมเพื่อกำจัดสิ่งน่าเกลียดเหล่านั้น()ออกไป อย่างไรก็ตามมันขึ้นอยู่กับความซับซ้อนของลำดับที่คุณต้องการจะสร้างได้ โดยทั่วไปแล้วหากลำดับของคุณสามารถแสดงโดยใช้ฟังก์ชันได้มากกว่าความซับซ้อนและน้ำตาลวากยสัมพันธ์ของเครื่องกำเนิดไฟฟ้าทั้งหมดสามารถซ่อนอยู่ในมัณฑนากรหรือฟังก์ชันที่เหมือนมัณฑนากร


9
OP ขอ oneliner และคุณนำเสนอมัณฑนากร 10 บรรทัดพร้อมซ้อนสามdefและปิด? ;)

2
@delnan ดี แต่ถ้าคุณกำหนดมัณฑนากรครั้งเดียวคุณสามารถมีหนึ่งสมุทรได้ไหม? ตามที่ฉันเข้าใจจุดประสงค์คือเพื่อให้เครื่องกำเนิดไฟฟ้าแบบไม่มีที่สิ้นสุดแต่ละตัวติดตั้งในบรรทัดเดียว และนี่คือสิ่งที่นำเสนอที่นี่ คุณสามารถมีคุณสามารถมี(2^x) (x)หากคุณปรับปรุงเล็กน้อยอาจเป็น fibonacci เป็นต้น
ก.ค.

ไม่ตอบคำถามของฉัน แต่แล้วคุณจะไม่รักความปิดสนิทเหล่านั้นได้อย่างไร? BTW ฉันค่อนข้างมั่นใจว่าคุณสามารถกำจัด parens พิเศษได้โดยการกำจัดseqและเยื้องรหัสกลับไปที่wrap
hugomg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.