Apakah mungkin untuk mengikuti tanpa i
?
for i in range(some_number):
# do something
Jika Anda hanya ingin melakukan sesuatu sebanyak N kali dan tidak perlu iterator.
Apakah mungkin untuk mengikuti tanpa i
?
for i in range(some_number):
# do something
Jika Anda hanya ingin melakukan sesuatu sebanyak N kali dan tidak perlu iterator.
Jawaban:
Dari atas kepalaku, tidak.
Saya pikir yang terbaik yang dapat Anda lakukan adalah sesuatu seperti ini:
def loop(f,n):
for i in xrange(n): f()
loop(lambda: <insert expression here>, 5)
Tapi saya pikir Anda bisa hidup dengan i
variabel tambahan .
Berikut adalah opsi untuk menggunakan _
variabel, yang pada kenyataannya, hanyalah variabel lain.
for _ in range(n):
do_something()
Catatan yang _
diberikan hasil terakhir yang dikembalikan dalam sesi python interaktif:
>>> 1+2
3
>>> _
3
Untuk alasan ini, saya tidak akan menggunakannya dengan cara ini. Saya tidak mengetahui adanya idiom seperti yang disebutkan oleh Ryan. Ini dapat mengacaukan penerjemah Anda.
>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9
Dan menurut tata bahasa Python , itu adalah nama variabel yang dapat diterima:
identifier ::= (letter|"_") (letter | digit | "_")*
_
membuatnya jelas bahwa itu harus diabaikan. Mengatakan tidak ada gunanya melakukan ini seperti mengatakan tidak ada gunanya mengomentari kode Anda - karena bagaimanapun juga akan melakukan hal yang sama.
Anda mungkin sedang mencari
for _ in itertools.repeat(None, times): ...
ini adalah cara tercepat untuk mengulang times
kali menggunakan Python.
Apa yang semua orang menyarankan Anda untuk menggunakan _ tidak mengatakan adalah _ sering digunakan sebagai jalan pintas ke salah satu fungsi gettext , jadi jika Anda ingin perangkat lunak Anda tersedia dalam lebih dari satu bahasa maka Anda sebaiknya menghindari menggunakannya untuk keperluan lain.
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')
_
sepertinya ide yang buruk, saya tidak keberatan berkonflik dengan itu.
Inilah gagasan acak yang memanfaatkan (menyalahgunakan?) Model data ( tautan 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
Saya ingin tahu apakah ada sesuatu seperti ini di perpustakaan standar?
__nonzero__
dengan efek samping adalah ide yang mengerikan.
__call__
sebagai gantinya. while x():
tidak terlalu sulit untuk ditulis.
Counter
; tentu saja, itu tidak dicadangkan atau dalam lingkup bawaan, tetapi collections.Counter
merupakan suatu hal , dan membuat kelas dengan nama yang sama berisiko membingungkan pengelola (bukan berarti ini sudah tidak mempertaruhkan yang sudah ada).
Anda dapat menggunakan _11 (atau nomor apa pun atau pengidentifikasi tidak valid lainnya) untuk mencegah tabrakan nama dengan gettext. Setiap kali Anda menggunakan underscore + pengidentifikasi tidak valid Anda mendapatkan nama dummy yang dapat digunakan untuk loop.
Mungkin jawabannya tergantung pada masalah apa yang Anda miliki dengan menggunakan iterator? dapat digunakan
i = 100
while i:
print i
i-=1
atau
def loop(N, doSomething):
if not N:
return
print doSomething(N)
loop(N-1, doSomething)
loop(100, lambda a:a)
tapi terus terang saya tidak melihat gunanya menggunakan pendekatan seperti itu
sys.getrecursionlimit()
(yang default ke suatu tempat di empat rendah rentang digit pada CPython); menggunakan sys.setrecursionlimit
akan menaikkan batas, tetapi pada akhirnya Anda akan mencapai batas C stack dan penerjemah akan mati dengan stack overflow (tidak hanya meningkatkan nice RuntimeError
/ RecursionError
).
t=0
for _ in range(10):
print t
t = t+1
KELUARAN:
0
1
2
3
4
5
6
7
8
9
Alih-alih penghitung yang tidak dibutuhkan, sekarang Anda memiliki daftar yang tidak dibutuhkan. Solusi terbaik adalah dengan menggunakan variabel yang dimulai dengan "_", yang memberi tahu checker sintaks bahwa Anda sadar Anda tidak menggunakan variabel.
x = range(5)
while x:
x.pop()
print "Work!"
Saya biasanya setuju dengan solusi yang diberikan di atas. Yaitu dengan:
for
-loop (2 dan lebih banyak baris)while
penghitung normal (3 dan lebih banyak baris)__nonzero__
implementasi (banyak lagi baris)Jika seseorang ingin mendefinisikan objek seperti pada # 3 saya akan merekomendasikan menerapkan protokol untuk dengan kata kunci atau menerapkan contextlib .
Selanjutnya saya mengusulkan solusi lain. Ini adalah 3 liner dan bukan dari keanggunan tertinggi, tetapi menggunakan paket itertools dan dengan demikian mungkin menarik.
from itertools import (chain, repeat)
times = chain(repeat(True, 2), repeat(False))
while next(times):
print 'do stuff!'
Dalam contoh ini 2 adalah berapa kali untuk mengulang loop. rantai membungkus dua iterator berulang , yang pertama terbatas tetapi yang kedua tak terbatas. Ingatlah bahwa ini adalah objek iterator sejati, karenanya mereka tidak memerlukan memori tak terbatas. Jelas ini jauh lebih lambat maka solusi # 1 . Kecuali ditulis sebagai bagian dari suatu fungsi mungkin diperlukan pembersihan untuk variabel kali .
chain
tidak perlu, times = repeat(True, 2); while next(times, False):
melakukan hal yang sama.
Kami bersenang-senang dengan yang berikut ini, menarik untuk dibagikan:
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()
Hasil:
0
1
2
3
4
5
6
---------
7
Jika do_something
fungsi sederhana atau dapat dibungkus menjadi satu, map()
kaleng sederhana do_something
range(some_number)
kali:
# 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)
Jika Anda ingin meneruskan argumen do_something
, Anda juga mungkin menemukan bahwa resep itertoolsrepeatfunc
terbaca dengan baik:
Untuk memberikan argumen yang sama:
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)
Untuk memberikan argumen yang berbeda:
argses = [(1, 2), (3, 4), ...]
deque(starmap(do_something, argses), 0)
Jika Anda benar - benar ingin menghindari meletakkan sesuatu dengan nama (baik variabel iterasi seperti dalam OP, atau daftar yang tidak diinginkan atau generator yang tidak diinginkan mengembalikan true jumlah waktu yang diinginkan) Anda dapat melakukannya jika Anda benar-benar ingin:
for type('', (), {}).x in range(somenumber):
dosomething()
Trik yang digunakan adalah membuat kelas anonim type('', (), {})
yang menghasilkan kelas dengan nama kosong, tetapi NB yang tidak dimasukkan dalam ruang nama lokal atau global (bahkan jika nama yang kosong disediakan). Kemudian Anda menggunakan anggota kelas itu sebagai variabel iterasi yang tidak dapat dijangkau karena kelas yang menjadi anggotanya tidak dapat dijangkau.
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
Diambil dari http://docs.python.org/2/library/itertools.html
Bagaimana dengan:
while range(some_number):
#do something
range(some_number)
selalu benar!
some_number
kurang dari atau sama dengan 0
, itu tidak terbatas, tidak pernah berjalan. :-) Dan itu agak tidak efisien untuk loop tak terbatas (terutama pada Py2), karena itu menciptakan segar list
(Py2) atau range
objek (Py3) untuk setiap tes (itu bukan konstan dari sudut pandang penerjemah, ia harus memuat range
dan some_number
setiap loop, panggil range
, lalu uji hasilnya).