Thêm cách Pythonic để chạy một quy trình X lần


90

Cái nào nhiều pythonic hơn?

Trong khi lặp lại:

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

Vòng lặp for:

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

Chỉnh sửa: không trùng lặp vì điều này có câu trả lời để xác định cái nào rõ ràng hơn, so với cách chạy một phạm vi mà không có 'i' - mặc dù điều đó cuối cùng là thanh lịch nhất


8
Ủng hộ để bù lại số phiếu phản đối: nếu Lionel hỏi câu hỏi này, những người khác có thể có cùng câu hỏi và các câu trả lời dưới đây sẽ hữu ích.
Eric O Lebigot

2
Thuật ngữ "Pythonic" đang được sử dụng quá mức. Đó là từ đồng nghĩa với "có thể đọc được" và "dễ hiểu". Ít nhất là bằng Python.
darioo

Câu trả lời:


111

Cá nhân:

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

nếu bạn không cần i. Nếu bạn sử dụng Python <3 và bạn muốn lặp lại vòng lặp nhiều lần, hãy sử dụng xrangevì không cần tạo toàn bộ danh sách trước.


15
Hãy để ý đến việc _ được ánh xạ đến chức năng dịch gettext.
Gintautas Miliauskas

Cảm ơn vì câu trả lời này; đây là lý do chính khiến tôi không sử dụng vòng lặp for vì tôi có một biến không được sử dụng trong "i".
Lionel

6
_ cũng giống như bất kỳ biến nào khác. Chỉ trong REPL thì nó mới có bất kỳ ý nghĩa cụ thể nào. OP cũng có thể gắn bó với i.
vezult 14/12/12

2
@vezult Tôi thích điều này vì nó làm rõ rằng biến không được sử dụng trong câu lệnh. Có lẽ có một lý do nào đó làm lu mờ điều này để gắn bó với i?
ryanjdillon

6
Tôi là một người tin tưởng vào việc thêm ngựa con, đặc biệt là khi nó có vẻ thích hợp ... cho ngựa trong phạm vi (50): print ("lân") #python 3
Paul

3

Vòng lặp for chắc chắn là khó hiểu hơn, vì nó sử dụng cấp độ cao hơn được tích hợp sẵn của Python để truyền đạt những gì bạn đang làm rõ ràng và ngắn gọn hơn. Chi phí của dải ô so với xrange và việc gán một ibiến không sử dụng , xuất phát từ việc không có câu lệnh như repeatcâu lệnh của Verilog . Lý do chính để gắn bó với giải pháp cho phạm vi là các cách khác phức tạp hơn. Ví dụ:

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"

Sử dụng lặp lại thay vì phạm vi ở đây ít rõ ràng hơn vì nó không được biết đến nhiều như một hàm và phức tạp hơn vì bạn cần nhập nó. Các hướng dẫn phong cách chính nếu bạn cần tham khảo là PEP 20 - The Zen of PythonPEP 8 - Style Guide for Python Code .

Chúng tôi cũng lưu ý rằng phiên bản cho phạm vi là một ví dụ rõ ràng được sử dụng trong cả tham chiếuhướng dẫn ngôn ngữ , mặc dù trong trường hợp đó, giá trị được sử dụng. Nó có nghĩa là biểu mẫu này chắc chắn sẽ quen thuộc hơn sự mở rộng while của vòng lặp for kiểu C.


Sẽ không tốt hơn nếu sử dụng điều lặp lại trực tiếp, tức là: for s in repeat('This is run 10 times', 10): print s??
F1Rumors

Chắc chắn! Nhưng bản in trong mã mẫu chỉ là một ví dụ về một đoạn mã lặp lại, mà có thể không có đối tượng trung tâm.
Yann Vernier

Nhà phát triển cốt lõi Python cho biết điều này nhanh hơn so với việc sử dụng range() twitter.com/raymondh/status/1144527183341375488
Chris_Rands

Nó thực sự nhanh hơn, vì nó không cần phải tra cứu hoặc tạo một intđối tượng khác nhau cho mỗi lần lặp. Tuy nhiên, thời gian của lập trình viên có thể có giá trị hơn thời gian thực thi.
Yann Vernier

2

Nếu bạn đang theo đuổi các tác dụng phụ xảy ra trong vòng lặp, cá nhân tôi sẽ đi range()tiếp cận.

Nếu bạn quan tâm đến kết quả của bất kỳ hàm nào bạn gọi trong vòng lặp, tôi sẽ tìm hiểu danh sách hoặc mapcách tiếp cận. Một cái gì đó như thế này:

def f(n):
    return n * n

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

kết quả = (f for i in range (50))
Luka Rahne

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

@ralu, chỉ khi bạn không cần truy cập lặp lại hoặc ngẫu nhiên vào kết quả.
aaronasterling

2
kết quả = tuple (kết quả) và là cách nhanh hơn so với danh sách, vì cắt trên tuple là O (1)
Luka Rahne

-3

Làm thế nào về?

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

hoặc theo cách xấu xí hơn:

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

hoặc nếu bạn muốn xem lần cuối cùng thông qua:

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

Ở đâu:

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

Không có một cách thực sự nào để lặp lại điều gì đó. Tuy nhiên, đó là một cách tốt hơn:

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

Nếu bạn cần chuyển chỉ mục thì:

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

Hãy coi rằng nó trả về kết quả dưới dạng một tập hợp. Vì vậy, nếu bạn cần thu thập kết quả, nó có thể giúp ích.


Điều này không chỉ không thực sự tốt hơn (chi phí gọi hàm, biểu thức lambda ít được biết đến hơn, thu thập các kết quả không sử dụng trong danh sách), 10 không phải là một lặp lại.
Yann Vernier

Đúng, xrange (10) không phải 10. Tôi đã nói là tốt hơn vì bạn không cần viết hàm hoặc tạo vòng lặp. Tuy nhiên, như tôi đã nói không có một con đường nào thực sự. Tôi đã thay đổi mã, Cảm ơn.
Abi M.Sangarab
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.