Có thể làm theo mà không cần i
?
for i in range(some_number):
# do something
Nếu bạn chỉ muốn làm điều gì đó N số lần và không cần trình lặp.
Có thể làm theo mà không cần i
?
for i in range(some_number):
# do something
Nếu bạn chỉ muốn làm điều gì đó N số lần và không cần trình lặp.
Câu trả lời:
Tắt đầu tôi, không.
Tôi nghĩ điều tốt nhất bạn có thể làm là một cái gì đó như thế này:
def loop(f,n):
for i in xrange(n): f()
loop(lambda: <insert expression here>, 5)
Nhưng tôi nghĩ bạn chỉ có thể sống với i
biến phụ .
Đây là tùy chọn để sử dụng _
biến, trong thực tế, chỉ là một biến khác.
for _ in range(n):
do_something()
Lưu ý rằng _
được chỉ định kết quả cuối cùng được trả về trong phiên python tương tác:
>>> 1+2
3
>>> _
3
Vì lý do này, tôi sẽ không sử dụng nó theo cách này. Tôi không biết về bất kỳ thành ngữ nào như Ryan đã đề cập. Nó có thể gây rối cho thông dịch viên của bạn.
>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9
Và theo ngữ pháp Python , nó là một tên biến được chấp nhận:
identifier ::= (letter|"_") (letter | digit | "_")*
_
làm cho nó rõ ràng rằng nó nên được bỏ qua. Nói rằng không có điểm nào trong việc này giống như nói rằng không có điểm nào trong việc nhận xét mã của bạn - bởi vì dù sao nó cũng sẽ làm như vậy.
Bạn có thể đang tìm kiếm
for _ in itertools.repeat(None, times): ...
đây là cách nhanh nhất để lặp lại times
thời gian trong Python.
Điều mà mọi người đề nghị bạn sử dụng _ không nói là _ thường được sử dụng như một lối tắt đến một trong các chức năng gettext , vì vậy nếu bạn muốn phần mềm của mình có sẵn nhiều ngôn ngữ thì tốt nhất bạn nên tránh sử dụng nó cho các mục đích khác.
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')
_
có vẻ như là một ý tưởng tồi tệ, tôi sẽ không xung đột với nó.
Đây là một ý tưởng ngẫu nhiên sử dụng (lạm dụng?) Mô hình dữ liệu ( liên kết Py3 ).
class Counter(object):
def __init__(self, val):
self.val = val
def __nonzero__(self):
self.val -= 1
return self.val >= 0
__bool__ = __nonzero__ # Alias to Py3 name to make code work unchanged on Py2 and Py3
x = Counter(5)
while x:
# Do something
pass
Tôi tự hỏi nếu có một cái gì đó như thế này trong các thư viện tiêu chuẩn?
__nonzero__
với tác dụng phụ là một ý tưởng khủng khiếp.
__call__
thay thế. while x():
không khó để viết
Counter
; chắc chắn, nó không được bảo lưu hoặc trong phạm vi tích hợp, nhưng collections.Counter
là một điều , và làm cho một lớp cùng tên có nguy cơ gây nhầm lẫn cho người duy trì (không phải điều này chưa gây rủi ro cho điều đó).
Bạn có thể sử dụng _11 (hoặc bất kỳ số nào hoặc số nhận dạng không hợp lệ khác) để ngăn chặn việc đặt tên với gettext. Bất cứ khi nào bạn sử dụng dấu gạch dưới + định danh không hợp lệ, bạn sẽ nhận được một tên giả có thể được sử dụng trong vòng lặp.
Có thể câu trả lời sẽ phụ thuộc vào vấn đề bạn gặp phải khi sử dụng iterator? có thể được sử dụng
i = 100
while i:
print i
i-=1
hoặc là
def loop(N, doSomething):
if not N:
return
print doSomething(N)
loop(N-1, doSomething)
loop(100, lambda a:a)
nhưng thẳng thắn tôi thấy không có điểm nào trong việc sử dụng các phương pháp như vậy
sys.getrecursionlimit()
(mặc định ở đâu đó trong bốn mức thấp phạm vi chữ số trên CPython); việc sử dụng sys.setrecursionlimit
sẽ tăng giới hạn, nhưng cuối cùng, bạn đã đạt đến giới hạn ngăn xếp C và trình thông dịch sẽ chết với tràn ngăn xếp (không chỉ tăng đẹp RuntimeError
/ RecursionError
).
t=0
for _ in range(10):
print t
t = t+1
ĐẦU RA:
0
1
2
3
4
5
6
7
8
9
Thay vì một bộ đếm không cần thiết, bây giờ bạn có một danh sách không cần thiết. Giải pháp tốt nhất là sử dụng một biến bắt đầu bằng "_", thông báo cho người kiểm tra cú pháp rằng bạn biết rằng bạn không sử dụng biến đó.
x = range(5)
while x:
x.pop()
print "Work!"
Tôi thường đồng ý với các giải pháp được đưa ra ở trên. Cụ thể với:
for
-loop (2 dòng trở lên)while
đếm bình thường (3 dòng trở lên)__nonzero__
việc thực hiện (nhiều dòng hơn)Nếu một trong số đó là xác định một đối tượng như trong # 3, tôi sẽ khuyên bạn nên thực hiện giao thức với từ khóa hoặc áp dụng bối cảnh .
Hơn nữa tôi đề xuất một giải pháp khác. Nó là một lớp lót 3 và không phải là sang trọng tối cao, nhưng nó sử dụng gói itertools và do đó có thể được quan tâm.
from itertools import (chain, repeat)
times = chain(repeat(True, 2), repeat(False))
while next(times):
print 'do stuff!'
Trong các ví dụ 2 này là số lần lặp lại vòng lặp. chuỗi đang gói hai vòng lặp lặp lại , lần đầu tiên bị giới hạn nhưng lần thứ hai là vô hạn. Hãy nhớ rằng đây là những đối tượng lặp thực sự, do đó chúng không yêu cầu bộ nhớ vô hạn. Rõ ràng điều này chậm hơn nhiều so với giải pháp số 1 . Trừ khi được viết như là một phần của chức năng, nó có thể yêu cầu dọn sạch cho biến thời gian .
chain
là không cần thiết, times = repeat(True, 2); while next(times, False):
làm điều tương tự.
Chúng tôi đã có một số niềm vui với những điều sau đây, thú vị để chia sẻ như vậy:
class RepeatFunction:
def __init__(self,n=1): self.n = n
def __call__(self,Func):
for i in xrange(self.n):
Func()
return Func
#----usage
k = 0
@RepeatFunction(7) #decorator for repeating function
def Job():
global k
print k
k += 1
print '---------'
Job()
Các kết quả:
0
1
2
3
4
5
6
---------
7
Nếu do_something
là một hàm đơn giản hoặc có thể được gói trong một, thì một lần đơn giản map()
có thể do_something
range(some_number)
:
# Py2 version - map is eager, so it can be used alone
map(do_something, xrange(some_number))
# Py3 version - map is lazy, so it must be consumed to do the work at all;
# wrapping in list() would be equivalent to Py2, but if you don't use the return
# value, it's wastefully creating a temporary, possibly huge, list of junk.
# collections.deque with maxlen 0 can efficiently run a generator to exhaustion without
# storing any of the results; the itertools consume recipe uses it for that purpose.
from collections import deque
deque(map(do_something, range(some_number)), 0)
Nếu bạn muốn truyền đối số cho do_something
, bạn cũng có thể tìm thấy công thức itertoolsrepeatfunc
đọc tốt:
Để vượt qua các đối số tương tự:
from collections import deque
from itertools import repeat, starmap
args = (..., my args here, ...)
# Same as Py3 map above, you must consume starmap (it's a lazy generator, even on Py2)
deque(starmap(do_something, repeat(args, some_number)), 0)
Để vượt qua các đối số khác nhau:
argses = [(1, 2), (3, 4), ...]
deque(starmap(do_something, argses), 0)
Nếu bạn thực sự muốn tránh đặt một cái gì đó có tên (một biến lặp như trong OP, hoặc danh sách không mong muốn hoặc trình tạo không mong muốn trả về đúng thời gian mong muốn), bạn có thể làm điều đó nếu bạn thực sự muốn:
for type('', (), {}).x in range(somenumber):
dosomething()
Thủ thuật được sử dụng là tạo một lớp ẩn danh type('', (), {})
dẫn đến một lớp có tên trống, nhưng NB không được chèn vào không gian tên cục bộ hoặc toàn cầu (ngay cả khi tên không trống được cung cấp). Sau đó, bạn sử dụng một thành viên của lớp đó làm biến lặp không thể truy cập được vì lớp mà thành viên của nó không thể truy cập được.
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
Thế còn:
while range(some_number):
#do something
range(some_number)
luôn luôn đúng!
some_number
nhỏ hơn hoặc bằng 0
, nó không phải là vô hạn, nó chỉ không bao giờ chạy. :-) Và nó không hiệu quả đối với một vòng lặp vô hạn (đặc biệt là trên Py2), vì nó tạo ra một list
(Py2) hoặc range
đối tượng (Py3) mới cho mỗi thử nghiệm (nó không phải là hằng số theo quan điểm của trình thông dịch, nó phải tải range
và some_number
mỗi vòng lặp, gọi range
, sau đó kiểm tra kết quả).