To dobre pytanie! PyDev nawet oznacza „i” jako ostrzeżenie dla „nieużywanej zmiennej”. Poniższe rozwiązanie usuwa to ostrzeżenie.
Ashwin Nanjappa
@Ashwin Możesz użyć \ @UnusedVariable, aby usunąć to ostrzeżenie. Zauważ, że musiałem uciec od symbolu „at”, aby komentarz mógł przejść.
Raffi Khatchadourian
Zadaję ci to samo pytanie. Jest to denerwujące ostrzeżeniami pylint. Oczywiście możesz wyłączyć ostrzeżenia poprzez dodatkowe tłumienie, takie jak proponowany @Raffi Khatchadourian. Byłoby miło unikać ostrzeżeń pylint i komentarzy dotyczących tłumienia.
tangoal
Odpowiedzi:
110
Z czubka mojej głowy, nie.
Myślę, że najlepsze, co możesz zrobić, to coś takiego:
def loop(f,n):for i in xrange(n): f()
loop(lambda:<insert expression here>,5)
Ale myślę, że możesz po prostu żyć z dodatkową izmienną.
Oto opcja użycia _zmiennej, która w rzeczywistości jest tylko inną zmienną.
for _ in range(n):
do_something()
Zauważ, że _przypisany jest ostatni wynik, który powrócił w interaktywnej sesji Pythona:
>>>1+23>>> _3
Z tego powodu nie użyłbym tego w ten sposób. Nie znam żadnego idiomu wspomnianego przez Ryana. Może to zepsuć twojego tłumacza.
„Ale myślę, że możesz po prostu żyć z dodatkowym„ i ”„ Tak, to tylko akademicki punkt.
James McMahon
1
@nemo, możesz spróbować zrobić dla _ w zakresie (n): jeśli nie chcesz używać nazw alfanumerycznych.
Nieznany
Czy w takim przypadku _ jest zmienną? Czy jest to coś innego w Pythonie?
James McMahon
1
@nemo Tak, to tylko akceptowalna nazwa zmiennej. W tłumaczu automatycznie przypisuje się ostatnie utworzone wyrażenie.
Nieznany
3
@kurczak Jest punkt. Używanie _wyjaśnia, że należy go zignorować. Powiedzenie, że nie ma sensu tego robić, jest jak powiedzenie, że nie ma sensu komentować kodu - ponieważ i tak zrobiłby dokładnie to samo.
Lambda Fairy
69
Być może szukasz
for _ in itertools.repeat(None, times):...
jest to najszybszy sposób na iterację timesczasów w Pythonie.
Nie zajmowałem się wydajnością, byłem tylko ciekawy, czy istnieje szybszy sposób na napisanie oświadczenia. Chociaż sporadycznie używam Pythona od około 2 lat, nadal czuję, że brakuje mi wielu rzeczy. Itertools to jedna z tych rzeczy, dziękuję za informację.
James McMahon
5
To ciekawe, nie wiedziałem o tym. Właśnie spojrzałem na dokumenty itertools; ale zastanawiam się, dlaczego jest to szybsze niż użycie zasięgu lub xrange?
si28719e
5
@blackkettle: jest szybszy, ponieważ nie musi zwracać bieżącego indeksu iteracji, który jest mierzalną częścią kosztu xrange (i zakresu Pythona 3, który daje iterator, a nie listę). @nemo, zakres jest tak zoptymalizowany, jak to tylko możliwe, ale potrzeba zbudowania i zwrócenia listy jest nieuchronnie cięższą pracą niż iterator (w Py3 zakres zwraca iterator, taki jak xrange Py2; zgodność wsteczna nie pozwala na taką zmianę w Py2), szczególnie takiego, który nie musi zwracać zmiennej wartości.
Alex Martelli,
4
@Cristian, tak, wyraźnie przygotowuje i zwraca int Python za każdym razem, inc. gc działa, ma wymierny koszt - wewnętrzne korzystanie z licznika nie ma znaczenia.
Alex Martelli,
4
Teraz rozumiem. Różnica wynika z narzutu GC, a nie z „algorytmu”. Nawiasem mówiąc, przeprowadzam szybki test porównawczy, a przyspieszenie wyniosło ~ 1,42x.
Cristian Ciupitu
59
Ogólnym idiomem przypisywania wartości, która nie jest używana, jest jej nazwa _.
To, co wszyscy sugerują używać _ nie mówi, że _ jest często używany jako skrót do jednej z funkcji gettext , więc jeśli chcesz, aby twoje oprogramowanie było dostępne w więcej niż jednym języku, najlepiej jest unikać jego używania. do innych celów.
import gettext
gettext.bindtextdomain('myapplication','/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...print _('This is a translatable string.')
Dla mnie takie użycie _wydaje się okropnym pomysłem, nie miałbym nic przeciwko temu.
KeithWM
9
Oto przypadkowy pomysł, który wykorzystuje (nadużywa?) Model danych ( link Py3 ).
classCounter(object):def __init__(self, val):
self.val = val
def __nonzero__(self):
self.val -=1return self.val >=0
__bool__ = __nonzero__ # Alias to Py3 name to make code work unchanged on Py2 and Py3
x =Counter(5)while x:# Do somethingpass
Zastanawiam się, czy jest coś takiego w standardowych bibliotekach?
Myślę, że posiadanie metody takiej jak __nonzero__efekty uboczne to okropny pomysł.
ThiefMaster
2
Użyłbym __call__zamiast tego. while x():nie jest trudniejsze do napisania.
Jasmijn
1
Istnieje również argument za unikaniem nazwy Counter; pewnie, to nie jest zarezerwowane ani wbudowane, ale collections.Counterjest rzeczą , a zrobienie klasy o tej samej nazwie grozi zamieszaniem opiekuna (nie to, że to już nie ryzykuje).
ShadowRanger
7
Możesz użyć _11 (lub dowolnej liczby lub innego nieprawidłowego identyfikatora), aby zapobiec kolizji nazw z gettext. Za każdym razem, gdy użyjesz podkreślenia + nieprawidłowego identyfikatora, otrzymujesz fałszywą nazwę, której można użyć w pętli.
Uwaga: Python (zdecydowanie nie interpreter referencyjny CPython przynajmniej, prawdopodobnie nie większość innych) nie optymalizuje rekurencji ogona, więc N będzie ograniczony do czegoś w sąsiedztwie wartości sys.getrecursionlimit()(domyślnie gdzieś w dolnej czwórce zakres cyfr na CPython); użycie sys.setrecursionlimitzwiększy limit, ale w końcu osiągniesz limit stosu C, a tłumacz umrze z przepełnieniem stosu (nie tylko podniesienie ładnego RuntimeError/ RecursionError).
Zamiast niepotrzebnego licznika masz teraz niepotrzebną listę. Najlepszym rozwiązaniem jest użycie zmiennej zaczynającej się od „_”, która mówi kontrolerom składni, że masz świadomość, że nie używasz zmiennej.
Ogólnie zgadzam się z powyższymi rozwiązaniami. Mianowicie z:
Używanie podkreślenia w forpętli (2 i więcej linii)
Definiowanie normalnego whilelicznika (3 i więcej linii)
Deklaracja niestandardowej klasy z __nonzero__implementacją (wiele innych wierszy)
Jeśli ktoś jest określenie przedmiotu jak w # 3 Polecam dla wdrażania protokołu z hasła lub zastosować contextlib .
Dalej proponuję jeszcze inne rozwiązanie. Jest 3-liniowy i nie ma najwyższej elegancji, ale wykorzystuje pakiet itertools , a zatem może być interesujący.
from itertools import(chain, repeat)
times = chain(repeat(True,2), repeat(False))while next(times):print'do stuff!'
W tym przykładzie 2 oznacza liczbę powtórzeń pętli. łańcuch owija dwa powtarzające się iteratory, pierwszy jest ograniczony, ale drugi jest nieskończony. Pamiętaj, że są to prawdziwe obiekty iteratora, dlatego nie wymagają nieskończonej pamięci. Oczywiście jest to znacznie wolniejsze niż rozwiązanie nr 1 . Chyba napisany jako część funkcji może wymagać oczyszczenia do krotnie zmiennej.
chainjest niepotrzebne, times = repeat(True, 2); while next(times, False):robi to samo.
AChampion
0
Mieliśmy trochę zabawy z następującymi, którymi warto się podzielić:
classRepeatFunction:def __init__(self,n=1): self.n = n
def __call__(self,Func):for i in xrange(self.n):Func()returnFunc#----usage
k =0@RepeatFunction(7)#decorator for repeating functiondefJob():global k
print k
k +=1print'---------'Job()
Jeśli do_somethingjest to prosta funkcja lub może być w nią zapakowana, proste czasy map()mogą do_somethingrange(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)
Jeśli chcesz przekazać argumenty do_something, może się okazać, że przepis itertoolsrepeatfunc brzmi dobrze:
Aby przekazać te same argumenty:
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)
Jeśli naprawdę chcesz uniknąć umieszczenia czegoś o nazwie (zmienna iteracyjna jak w OP, niechciana lista lub niechciany generator zwracający prawdziwą pożądaną ilość czasu), możesz to zrobić, jeśli naprawdę chcesz:
for type('',(),{}).x in range(somenumber):
dosomething()
Stosowana sztuczka polega na utworzeniu anonimowej klasy, type('', (), {})której wynikiem jest klasa o pustej nazwie, ale należy pamiętać, że nie jest ona wstawiana do lokalnej lub globalnej przestrzeni nazw (nawet jeśli podano niepustą nazwę). Następnie używasz członka tej klasy jako zmiennej iteracyjnej, która jest nieosiągalna, ponieważ klasa, do której należy, jest nieosiągalna.
Oczywiście jest to celowo patologiczne, więc krytykowanie go nie ma sensu, ale zauważę tutaj dodatkową pułapkę. W CPython, interpretatorze referencyjnym, definicje klas są naturalnie cykliczne (tworzenie klasy nieuchronnie tworzy cykl referencyjny, który zapobiega deterministycznemu czyszczeniu klasy na podstawie zliczania referencji). Oznacza to, że czekasz na cyklicznym GC, aby rozpocząć i posprzątać klasę. Zwykle będzie gromadzony jako część młodszego pokolenia, które domyślnie jest gromadzone często, ale mimo to każda pętla oznacza ~ 1,5 KB śmieci w / nieokreślistyczny czas życia.
ShadowRanger
Zasadniczo, aby uniknąć nazwanej zmiennej, która byłaby (zwykle) deterministycznie czyszczona w każdej pętli (gdy jest ona odbijana, a stara wartość czyszczona), tworzysz ogromną nienazwaną zmienną, która jest czyszczona w sposób niedeterministyczny i może łatwo trwa dłuzej.
ShadowRanger
-2
#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))
To nieskończona pętla, ponieważ warunek range(some_number)jest zawsze spełniony!
śmiertelny
@deadly: Cóż, jeśli some_numberjest mniejsza lub równa 0, nie jest nieskończona, po prostu nigdy nie działa. :-) Jest to raczej nieefektywne w przypadku nieskończonej pętli (szczególnie w Py2), ponieważ tworzy nowy list(Py2) lub rangeobiekt (Py3) dla każdego testu (nie jest to stały z punktu widzenia interpretera, musi się załadować rangei some_numberkażdą pętlę, wywołaj range, a następnie przetestuj wynik).
Odpowiedzi:
Z czubka mojej głowy, nie.
Myślę, że najlepsze, co możesz zrobić, to coś takiego:
Ale myślę, że możesz po prostu żyć z dodatkową
i
zmienną.Oto opcja użycia
_
zmiennej, która w rzeczywistości jest tylko inną zmienną.Zauważ, że
_
przypisany jest ostatni wynik, który powrócił w interaktywnej sesji Pythona:Z tego powodu nie użyłbym tego w ten sposób. Nie znam żadnego idiomu wspomnianego przez Ryana. Może to zepsuć twojego tłumacza.
Zgodnie z gramatyką Pythona jest to dopuszczalna nazwa zmiennej:
źródło
_
wyjaśnia, że należy go zignorować. Powiedzenie, że nie ma sensu tego robić, jest jak powiedzenie, że nie ma sensu komentować kodu - ponieważ i tak zrobiłby dokładnie to samo.Być może szukasz
jest to najszybszy sposób na iterację
times
czasów w Pythonie.źródło
Ogólnym idiomem przypisywania wartości, która nie jest używana, jest jej nazwa
_
.źródło
To, co wszyscy sugerują używać _ nie mówi, że _ jest często używany jako skrót do jednej z funkcji gettext , więc jeśli chcesz, aby twoje oprogramowanie było dostępne w więcej niż jednym języku, najlepiej jest unikać jego używania. do innych celów.
źródło
_
wydaje się okropnym pomysłem, nie miałbym nic przeciwko temu.Oto przypadkowy pomysł, który wykorzystuje (nadużywa?) Model danych ( link Py3 ).
Zastanawiam się, czy jest coś takiego w standardowych bibliotekach?
źródło
__nonzero__
efekty uboczne to okropny pomysł.__call__
zamiast tego.while x():
nie jest trudniejsze do napisania.Counter
; pewnie, to nie jest zarezerwowane ani wbudowane, alecollections.Counter
jest rzeczą , a zrobienie klasy o tej samej nazwie grozi zamieszaniem opiekuna (nie to, że to już nie ryzykuje).Możesz użyć _11 (lub dowolnej liczby lub innego nieprawidłowego identyfikatora), aby zapobiec kolizji nazw z gettext. Za każdym razem, gdy użyjesz podkreślenia + nieprawidłowego identyfikatora, otrzymujesz fałszywą nazwę, której można użyć w pętli.
źródło
Być może odpowiedź zależy od tego, jaki masz problem z używaniem iteratora? może być użyty
lub
ale szczerze mówiąc, nie widzę sensu w stosowaniu takich podejść
źródło
sys.getrecursionlimit()
(domyślnie gdzieś w dolnej czwórce zakres cyfr na CPython); użyciesys.setrecursionlimit
zwiększy limit, ale w końcu osiągniesz limit stosu C, a tłumacz umrze z przepełnieniem stosu (nie tylko podniesienie ładnegoRuntimeError
/RecursionError
).WYNIK:
źródło
Zamiast niepotrzebnego licznika masz teraz niepotrzebną listę. Najlepszym rozwiązaniem jest użycie zmiennej zaczynającej się od „_”, która mówi kontrolerom składni, że masz świadomość, że nie używasz zmiennej.
źródło
Ogólnie zgadzam się z powyższymi rozwiązaniami. Mianowicie z:
for
pętli (2 i więcej linii)while
licznika (3 i więcej linii)__nonzero__
implementacją (wiele innych wierszy)Jeśli ktoś jest określenie przedmiotu jak w # 3 Polecam dla wdrażania protokołu z hasła lub zastosować contextlib .
Dalej proponuję jeszcze inne rozwiązanie. Jest 3-liniowy i nie ma najwyższej elegancji, ale wykorzystuje pakiet itertools , a zatem może być interesujący.
W tym przykładzie 2 oznacza liczbę powtórzeń pętli. łańcuch owija dwa powtarzające się iteratory, pierwszy jest ograniczony, ale drugi jest nieskończony. Pamiętaj, że są to prawdziwe obiekty iteratora, dlatego nie wymagają nieskończonej pamięci. Oczywiście jest to znacznie wolniejsze niż rozwiązanie nr 1 . Chyba napisany jako część funkcji może wymagać oczyszczenia do krotnie zmiennej.
źródło
chain
jest niepotrzebne,times = repeat(True, 2); while next(times, False):
robi to samo.Mieliśmy trochę zabawy z następującymi, którymi warto się podzielić:
Wyniki:
źródło
Jeśli
do_something
jest to prosta funkcja lub może być w nią zapakowana, proste czasymap()
mogądo_something
range(some_number)
:Jeśli chcesz przekazać argumenty
do_something
, może się okazać, że przepis itertoolsrepeatfunc
brzmi dobrze:Aby przekazać te same argumenty:
Aby przekazać różne argumenty:
źródło
Jeśli naprawdę chcesz uniknąć umieszczenia czegoś o nazwie (zmienna iteracyjna jak w OP, niechciana lista lub niechciany generator zwracający prawdziwą pożądaną ilość czasu), możesz to zrobić, jeśli naprawdę chcesz:
Stosowana sztuczka polega na utworzeniu anonimowej klasy,
type('', (), {})
której wynikiem jest klasa o pustej nazwie, ale należy pamiętać, że nie jest ona wstawiana do lokalnej lub globalnej przestrzeni nazw (nawet jeśli podano niepustą nazwę). Następnie używasz członka tej klasy jako zmiennej iteracyjnej, która jest nieosiągalna, ponieważ klasa, do której należy, jest nieosiągalna.źródło
Zaczerpnięte z http://docs.python.org/2/library/itertools.html
źródło
Co powiesz na:
źródło
range(some_number)
jest zawsze spełniony!some_number
jest mniejsza lub równa0
, nie jest nieskończona, po prostu nigdy nie działa. :-) Jest to raczej nieefektywne w przypadku nieskończonej pętli (szczególnie w Py2), ponieważ tworzy nowylist
(Py2) lubrange
obiekt (Py3) dla każdego testu (nie jest to stały z punktu widzenia interpretera, musi się załadowaćrange
isome_number
każdą pętlę, wywołajrange
, a następnie przetestuj wynik).