วิธี Pythonic เพิ่มเติมในการรัน Process X Times


90

pythonic ไหนมากกว่ากัน?

ในขณะที่วนซ้ำ:

count = 0
while count < 50:
    print "Some thing"
    count = count + 1

สำหรับห่วง:

for i in range(50):
    print "Some thing"

แก้ไข: ไม่ซ้ำกันเนื่องจากมีคำตอบเพื่อพิจารณาว่าข้อใดชัดเจนกว่าเทียบกับวิธีเรียกใช้ช่วงโดยไม่มี 'i' แม้ว่าจะจบลงด้วยความสง่างามที่สุด


9
การโหวตเพิ่มเพื่อชดเชยการโหวตที่ลดลง: หากไลโอเนลถามคำถามนี้คนอื่น ๆ อาจมีคำถามเดียวกันและคำตอบด้านล่างจะเป็นประโยชน์
Eric O Lebigot

2
คำว่า "Pythonic" ถูกใช้มากเกินไป เป็นคำพ้องความหมายสำหรับ "อ่านได้" และ "เข้าใจได้ง่าย" ใน Python อย่างน้อย
darioo

คำตอบ:


115

ส่วนตัว:

for _ in range(50):
    print "Some thing"

iถ้าคุณไม่จำเป็นต้อง หากคุณใช้ Python <3 และคุณต้องการวนซ้ำหลาย ๆ ครั้งให้ใช้xrangeเนื่องจากไม่จำเป็นต้องสร้างรายการทั้งหมดก่อนล่วงหน้า


15
ระวัง _ ถูกแมปกับฟังก์ชั่นแปล gettext
Gintautas Miliauskas

ขอบคุณสำหรับคำตอบนี้ นี่เป็นสาเหตุหลักที่ฉันไม่ใช้ for-loop เนื่องจากฉันมีตัวแปรที่ไม่ได้ใช้ใน "i"
Lionel

6
_ ก็เหมือนกับตัวแปรอื่น ๆ เฉพาะใน REPL เท่านั้นที่มีความสำคัญเป็นพิเศษ OP อาจติดด้วยiเช่นกัน
vezult

2
@vezult ฉันชอบสิ่งนี้เพราะมันทำให้ชัดเจนว่าตัวแปรไม่ได้ถูกใช้ในคำสั่ง อาจมีเหตุผลที่ทำให้สิ่งนี้ยึดติดกับสิ่งนี้iหรือไม่?
ryanjdillon

7
ฉันเชื่อมั่นในการเพิ่มม้าโดยเฉพาะเมื่อมันฟังดูเหมาะสม ... สำหรับม้าในระยะ (50): print ("Neigh") #python 3
Paul

3

สำหรับลูปนั้นเป็นไพโธนิกมากกว่าอย่างแน่นอนเนื่องจากมันใช้ฟังก์ชันที่สร้างขึ้นในระดับที่สูงขึ้นของ Python เพื่อถ่ายทอดสิ่งที่คุณกำลังทำทั้งอย่างชัดเจนและรัดกุมยิ่งขึ้น ค่าโสหุ้ยของ range vs xrange และการกำหนดiตัวแปรที่ไม่ได้ใช้เกิดจากการไม่มีคำสั่งเช่นrepeatคำสั่งของ Verilog เหตุผลหลักที่ต้องยึดติดกับโซลูชัน for range คือวิธีอื่นที่ซับซ้อนกว่า ตัวอย่างเช่น:

from itertools import repeat

for unused in repeat(None, 10):
    del unused   # redundant and inefficient, the name is clear enough
    print "This is run 10 times"

การใช้การทำซ้ำแทนช่วงที่นี่มีความชัดเจนน้อยกว่าเนื่องจากฟังก์ชั่นไม่เป็นที่รู้จักกันดีและซับซ้อนกว่าเนื่องจากคุณต้องนำเข้า คู่มือสไตล์ถ้าคุณจำเป็นต้องมีการอ้างอิงPEP 20 - เซนของงูใหญ่และPEP ที่ 8 - คู่มือสไตล์สำหรับงูหลามรหัส

นอกจากนี้เรายังทราบด้วยว่าเวอร์ชันสำหรับช่วงเป็นตัวอย่างที่ชัดเจนซึ่งใช้ทั้งในการอ้างอิงภาษาและบทช่วยสอนแม้ว่าในกรณีนี้จะใช้ค่า หมายความว่ารูปแบบจะต้องคุ้นเคยมากกว่าการขยายในขณะที่รูปแบบ C สำหรับลูป


จะไม่ดีกว่าที่จะใช้สิ่งที่ซ้ำโดยตรงกล่าวคือ: for s in repeat('This is run 10 times', 10): print s??
F1Rumors

แน่นอน! แต่การพิมพ์ในโค้ดตัวอย่างเป็นเพียงตัวอย่างของโค้ดส่วนที่ซ้ำ ๆ กันซึ่งอาจไม่มีวัตถุกลาง
Yann Vernier

นักพัฒนาหลักของ Python กล่าวว่าเร็วกว่าการใช้range() twitter.com/raymondh/status/1144527183341375488
Chris_Rands

มันเร็วกว่าแน่นอนเพราะไม่จำเป็นต้องค้นหาหรือสร้างintออบเจ็กต์อื่นสำหรับการทำซ้ำแต่ละครั้ง อย่างไรก็ตามเวลาของโปรแกรมเมอร์อาจมีค่ามากกว่าเวลาดำเนินการ
Yann Vernier

2

หากคุณอยู่หลังจากผลข้างเคียงที่เกิดขึ้นภายในลูปฉันจะไปหาไฟล์ range()แนวทางนี้เป็นการส่วนตัว

หากคุณสนใจเกี่ยวกับผลลัพธ์ของฟังก์ชันใด ๆ ที่คุณเรียกใช้ในลูปฉันจะไปทำความเข้าใจกับรายการหรือmapแนวทาง สิ่งนี้:

def f(n):
    return n * n

results = [f(i) for i in range(50)]
# or using map:
results = map(f, range(50))

ผลลัพธ์ = (f สำหรับฉันในช่วง (50))
Luka Rahne

1
results = itertools.imap (f, range (50))
Luka Rahne

@ralu เฉพาะในกรณีที่คุณไม่ต้องการการเข้าถึงซ้ำหรือสุ่มในผลลัพธ์แม้ว่า
aaronasterling

2
result = tuple (ผลลัพธ์) และเร็วกว่า list เนื่องจากการแบ่ง tuple เป็น O (1)
Luka Rahne

-3

เกี่ยวกับ?

while BoolIter(N, default=True, falseIndex=N-1):
    print 'some thing'

หรือในทางที่น่าเกลียดกว่า:

for _ in BoolIter(N):
    print 'doing somthing'

หรือหากคุณต้องการจับภาพครั้งสุดท้ายผ่าน:

for lastIteration in BoolIter(N, default=False, trueIndex=N-1):
    if not lastIteration:
        print 'still going'
    else:
        print 'last time'

ที่ไหน:

class BoolIter(object):

    def __init__(self, n, default=False, falseIndex=None, trueIndex=None, falseIndexes=[], trueIndexes=[], emitObject=False):
        self.n = n
        self.i = None
        self._default = default
        self._falseIndexes=set(falseIndexes)
        self._trueIndexes=set(trueIndexes)
        if falseIndex is not None:
            self._falseIndexes.add(falseIndex)
        if trueIndex is not None:
            self._trueIndexes.add(trueIndex)
        self._emitObject = emitObject


    def __iter__(self):
        return self

    def next(self):
        if self.i is None:
            self.i = 0
        else:
            self.i += 1
        if self.i == self.n:
            raise StopIteration
        if self._emitObject:
            return self
        else:
            return self.__nonzero__()

    def __nonzero__(self):
        i = self.i
        if i in self._trueIndexes:
            return True
        if i in self._falseIndexes:
            return False
        return self._default

    def __bool__(self):
        return self.__nonzero__()

-5

ไม่มีวิธีการทำซ้ำบางสิ่งอย่างมาก อย่างไรก็ตามเป็นวิธีที่ดีกว่า:

map(lambda index:do_something(), xrange(10))

หากคุณต้องการส่งดัชนีแล้ว:

map(lambda index:do_something(index), xrange(10))

พิจารณาว่าจะส่งคืนผลลัพธ์เป็นคอลเล็กชัน ดังนั้นหากคุณต้องการรวบรวมผลลัพธ์ก็สามารถช่วยได้


ไม่เพียง แต่สิ่งนี้จะไม่ดีขึ้นจริงๆ (ค่าใช้จ่ายในการเรียกฟังก์ชัน, นิพจน์แลมด้าที่รู้จักกันน้อยกว่า, รวบรวมผลลัพธ์ที่ไม่ได้ใช้ในรายการ), 10 ไม่สามารถทำซ้ำได้
Yann Vernier

ใช่ xrange (10) ไม่ใช่ 10 ฉันว่ามันดีกว่าเพราะคุณไม่จำเป็นต้องเขียนฟังก์ชันหรือทำวนซ้ำ อย่างไรก็ตามอย่างที่บอกว่าไม่มีวิธี pythonic ที่แท้จริง ฉันเปลี่ยนรหัสแล้วขอบคุณ
Abi M. Sangarab
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.