เป็นไปได้หรือไม่ที่จะทำตามโดยไม่ต้องทำi
?
for i in range(some_number):
# do something
หากคุณต้องการทำบางสิ่งบางอย่างจำนวน N ครั้งและไม่ต้องการตัววนซ้ำ
เป็นไปได้หรือไม่ที่จะทำตามโดยไม่ต้องทำi
?
for i in range(some_number):
# do something
หากคุณต้องการทำบางสิ่งบางอย่างจำนวน N ครั้งและไม่ต้องการตัววนซ้ำ
คำตอบ:
ปิดส่วนหัวของฉันไม่
ฉันคิดว่าสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือสิ่งนี้:
def loop(f,n):
for i in xrange(n): f()
loop(lambda: <insert expression here>, 5)
แต่ฉันคิดว่าคุณสามารถอยู่กับi
ตัวแปรพิเศษได้
นี่คือตัวเลือกในการใช้_
ตัวแปรซึ่งในความเป็นจริงเป็นเพียงตัวแปรอื่น
for _ in range(n):
do_something()
โปรดทราบว่า_
มีการกำหนดผลลัพธ์สุดท้ายที่ส่งคืนในเซสชัน python แบบโต้ตอบ:
>>> 1+2
3
>>> _
3
ด้วยเหตุนี้ฉันจะไม่ใช้มันในลักษณะนี้ ฉันไม่รู้สำนวนใด ๆ ตามที่ Ryan กล่าวถึง มันอาจทำให้ล่ามของคุณยุ่งเหยิง
>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9
และตามPython ไวยากรณ์มันเป็นชื่อตัวแปรที่ยอมรับได้:
identifier ::= (letter|"_") (letter | digit | "_")*
_
ทำให้ชัดเจนว่าควรละเว้น การบอกว่าไม่มีจุดในการทำเช่นนี้เหมือนกับการบอกว่าไม่มีจุดในการแสดงความคิดเห็นรหัสของคุณ - เพราะมันจะทำเหมือนกันทุกประการ
คุณอาจกำลังมองหา
for _ in itertools.repeat(None, times): ...
นี่เป็นวิธีที่เร็วที่สุดในการทำซ้ำtimes
เวลาใน Python
_
สำนวนทั่วไปสำหรับการกำหนดค่าที่ไม่ได้ถูกใช้เป็นชื่อให้มัน
for _ in range(times):
do_stuff()
สิ่งที่ทุกคนแนะนำให้คุณใช้ _ ไม่ได้กล่าวคือ _ มักใช้เป็นทางลัดไปยังหนึ่งในฟังก์ชั่นgettextดังนั้นหากคุณต้องการให้ซอฟต์แวร์ของคุณมีภาษามากกว่าหนึ่งภาษาคุณควรหลีกเลี่ยงการใช้มัน เพื่อวัตถุประสงค์อื่น
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')
_
ดูเหมือนเป็นความคิดที่แย่มากฉันไม่รังเกียจที่จะขัดแย้งกับมัน
นี่คือแนวคิดแบบสุ่มที่ใช้ (ละเมิด?) ตัวแบบข้อมูล ( ลิงก์ 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
ฉันสงสัยว่ามีอะไรแบบนี้ในห้องสมุดมาตรฐานหรือไม่?
__nonzero__
กับผลข้างเคียงเป็นความคิดที่น่ากลัว
__call__
แทน while x():
ไม่ใช่เรื่องยากที่จะเขียน
Counter
; แน่นอนว่ามันไม่ได้ถูกสงวนไว้หรืออยู่ในขอบเขต แต่collections.Counter
เป็นสิ่งและทำให้คลาสที่มีชื่อเดียวกันมีความเสี่ยงต่อความสับสนของผู้ดูแล
คุณสามารถใช้ _11 (หรือหมายเลขใด ๆ หรือตัวระบุที่ไม่ถูกต้องอื่น ๆ ) เพื่อป้องกันการตั้งชื่อด้วย gettext เมื่อใดก็ตามที่คุณใช้ขีดเส้นใต้ + ตัวระบุที่ไม่ถูกต้องคุณจะได้รับชื่อดัมมี่ที่สามารถใช้ในการวนซ้ำ
อาจเป็นคำตอบนั้นขึ้นอยู่กับปัญหาที่คุณมีเมื่อใช้ตัววนซ้ำ? อาจจะใช้
i = 100
while i:
print i
i-=1
หรือ
def loop(N, doSomething):
if not N:
return
print doSomething(N)
loop(N-1, doSomething)
loop(100, lambda a:a)
แต่ตรงไปตรงมาฉันไม่เห็นจุดที่ใช้วิธีดังกล่าว
sys.getrecursionlimit()
(ซึ่งเป็นค่าเริ่มต้นสำหรับสี่ที่ต่ำ ช่วงหลักของ CPython); การใช้sys.setrecursionlimit
จะเพิ่มขีด จำกัด แต่ในที่สุดคุณจะถึงขีด จำกัด C ของสแต็กและล่ามจะตายเมื่อมีสแตกมากเกินไป(ไม่ใช่แค่เพิ่มความสวยงามRuntimeError
/ RecursionError
)
t=0
for _ in range(10):
print t
t = t+1
เอาท์พุท:
0
1
2
3
4
5
6
7
8
9
แทนที่จะเป็นตัวนับที่ไม่จำเป็นตอนนี้คุณมีรายการที่ไม่จำเป็น ทางออกที่ดีที่สุดคือการใช้ตัวแปรที่ขึ้นต้นด้วย "_" ซึ่งจะบอกตัวตรวจสอบไวยากรณ์ที่คุณทราบว่าคุณไม่ได้ใช้ตัวแปร
x = range(5)
while x:
x.pop()
print "Work!"
โดยทั่วไปฉันเห็นด้วยกับวิธีแก้ปัญหาที่ระบุไว้ข้างต้น คือ:
for
-loop (2 บรรทัดขึ้นไป)while
นับ (3 บรรทัดขึ้นไป)__nonzero__
การนำไปใช้ (อีกหลายบรรทัด)หากมีการกำหนดวัตถุเช่นเดียวกับใน# 3ฉันขอแนะนำให้ใช้โปรโตคอลสำหรับกับคำหลักหรือใช้บริบท contextlib
ต่อไปฉันขอเสนอวิธีแก้ปัญหาอื่น มันเป็นซับใน 3 อันและไม่ได้มีความสง่างามอย่างสูงสุด แต่มันใช้แพ็คเกจitertoolsซึ่งอาจเป็นที่สนใจ
from itertools import (chain, repeat)
times = chain(repeat(True, 2), repeat(False))
while next(times):
print 'do stuff!'
ในตัวอย่างเหล่านี้2คือจำนวนครั้งในการวนซ้ำลูป ห่วงโซ่คือการวนซ้ำสองซ้ำตัวแรกจะถูก จำกัด แต่ตัวที่สองไม่มีที่สิ้นสุด โปรดจำไว้ว่าสิ่งเหล่านี้เป็นวัตถุตัววนซ้ำจริงดังนั้นพวกเขาจึงไม่ต้องการหน่วยความจำที่ไม่มีที่สิ้นสุด เห็นได้ชัดว่านี่เป็นช้ามากแล้ววิธีการแก้ปัญหา# 1 เว้นแต่จะเขียนเป็นส่วนหนึ่งของฟังก์ชั่นอาจต้องล้างค่าสำหรับตัวแปรครั้ง
chain
ไม่จำเป็นtimes = repeat(True, 2); while next(times, False):
ทำในสิ่งเดียวกัน
เราสนุกกับสิ่งต่อไปนี้และน่าสนใจที่จะแบ่งปัน:
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()
ผล:
0
1
2
3
4
5
6
---------
7
ถ้าdo_something
เป็นฟังก์ชั่นที่เรียบง่ายหรือสามารถห่อในหนึ่งง่ายmap()
สามารถ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)
หากคุณต้องการส่งผ่านข้อโต้แย้งไปยังdo_something
คุณอาจพบว่าสูตรitertoolsrepeatfunc
อ่านได้ดี:
ในการผ่านข้อโต้แย้งเดียวกัน:
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)
ในการผ่านการโต้แย้งที่แตกต่าง:
argses = [(1, 2), (3, 4), ...]
deque(starmap(do_something, argses), 0)
หากคุณจริงๆต้องการที่จะหลีกเลี่ยงการวางบางสิ่งบางอย่างที่มีชื่อ (ทั้งตัวแปรซ้ำเช่นเดียวกับใน OP หรือรายการที่ไม่พึงประสงค์หรือเครื่องกำเนิดไฟฟ้าที่ไม่พึงประสงค์กลับมาจริงจำนวนเงินที่ต้องการของเวลา) คุณสามารถทำมันหากคุณต้องการจริงๆ:
for type('', (), {}).x in range(somenumber):
dosomething()
เคล็ดลับที่ใช้คือการสร้างคลาสที่ไม่ระบุชื่อtype('', (), {})
ซึ่งส่งผลให้คลาสมีชื่อว่างเปล่า แต่ NB ที่ไม่ได้แทรกไว้ในเนมสเปซท้องถิ่นหรือทั่วโลก (แม้ว่าจะมีการระบุชื่อที่ไม่ว่าง) จากนั้นคุณใช้สมาชิกของคลาสนั้นเป็นตัวแปรการวนซ้ำซึ่งไม่สามารถเข้าถึงได้เนื่องจากคลาสที่สมาชิกที่เป็นสมาชิกนั้นไม่สามารถเข้าถึงได้
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
เกี่ยวกับ:
while range(some_number):
#do something
range(some_number)
เป็นจริงเสมอ!
some_number
น้อยกว่าหรือเท่ากับ0
มันไม่ใช่อนันต์มันก็ไม่เคยวิ่ง :-) และค่อนข้างไม่มีประสิทธิภาพสำหรับการวนซ้ำไม่ จำกัด (โดยเฉพาะอย่างยิ่งใน Py2) เนื่องจากมันสร้างlist
(Py2) ใหม่หรือrange
วัตถุ (Py3) สำหรับการทดสอบแต่ละครั้ง (ไม่ใช่ค่าคงที่จากมุมมองของล่ามจึงต้องโหลดrange
และsome_number
ทุกลูปโทรrange
จากนั้นทดสอบผลลัพธ์)