هل من الممكن تنفيذ حلقة Python for range بدون متغير مكرر؟

StackOverflow https://stackoverflow.com/questions/818828

  •  03-07-2019
  •  | 
  •  

سؤال

هل من الممكن المتابعة بدون 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()

لاحظ أن _ يتم تعيين النتيجة الأخيرة التي عادت في جلسة الثعبان التفاعلية:

>>> 1+2
3
>>> _
3

لهذا السبب، وأود أن لا تستخدم في هذه الطريقة. لست على علم بأي لغة كما ذكر ريان. ما في وسعها لخبط مترجم الخاص بك.

>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9

وفقا ل بيثون قواعد ، وهو اسم متغير مقبول :

identifier ::= (letter|"_") (letter | digit | "_")*

نصائح أخرى

ويمكنك أن تبحث عن

for _ in itertools.repeat(None, times): ...

وهذا هو أسرع وسيلة لتكرار مرات times في بيثون.

وهذا المصطلح العام لتعيين إلى قيمة لا يستخدم هو تسميته _.

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

وأنا أتساءل عما إذا كان هناك شيء من هذا القبيل في المكتبات القياسية؟

ويمكنك استخدام _11 (أو أي رقم أو معرف صالح آخر) لمنع اسم-colision مع 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)

ولكن بصراحة لا أرى أي نقطة في استخدام هذه النهج

t=0    
for _ in range(10):
    print t
    t = t+1

وOUTPUT:

0
1 
2 
3 
4 
5 
6 
7
8
9

أنا أتفق بشكل عام مع الحلول المذكورة أعلاه.وهي مع:

  1. باستخدام الشرطة السفلية في for- حلقة (سطرين أو أكثر)
  2. تعريف عادي while العداد (3 خطوط وأكثر)
  3. الإعلان عن فئة مخصصة مع __nonzero__ التنفيذ (العديد من الخطوط)

إذا كان على المرء تحديد كائن كما في #3 أوصي بتنفيذ بروتوكول ل مع الكلمة الرئيسية أو تطبيق contextlib.

علاوة على ذلك أقترح حلاً آخر.وهي عبارة عن 3 بطانة وليست في غاية الأناقة ولكنها تستخدم com.itertools الحزمة وبالتالي قد تكون ذات فائدة.

from itertools import (chain, repeat)

times = chain(repeat(True, 2), repeat(False))
while next(times):
    print 'do stuff!'

في هذه الأمثلة 2 هو عدد مرات تكرار الحلقة. سلسلة هو التفاف اثنين يكرر التكرارات، الأول محدود ولكن الثاني لا نهائي.تذكر أن هذه كائنات مكررة حقيقية، وبالتالي فهي لا تتطلب ذاكرة لا نهائية.من الواضح أن هذا أبطأ بكثير من الحل #1.ما لم تتم كتابته كجزء من وظيفة، فقد يتطلب الأمر تنظيفًا له مرات عامل.

لقد استمتعنا بما يلي، ومن المثير للاهتمام مشاركته:

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، يمكنك أيضا العثور على itertools repeatfunc صفة يقرأ جيدا:

لتمرير نفس الحجج:

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)

وبدلا من عداد لزوم لها، والآن لديك قائمة لزوم لها. أفضل حل هو استخدام متغير الذي يبدأ ب "_"، الذي يروي لعبة الداما بناء الجملة التي كنت على بينة من أنك لا تستخدم المتغير.

x = range(5)
while x:
  x.pop()
  print "Work!"

اذا أنت حقًا تريد تجنب وضع شيء ما باسم (إما متغير تكرار كما في OP، أو قائمة غير مرغوب فيها أو مولد غير مرغوب فيه يعود صحيحًا خلال مقدار الوقت المطلوب) يمكنك القيام بذلك إذا كنت تريد حقًا:

for type('', (), {}).x in range(somenumber):
    dosomething()

الحيلة المستخدمة هي إنشاء فئة مجهولة type('', (), {}) مما يؤدي إلى فئة ذات اسم فارغ، ولكن لاحظ أنه لم يتم إدراجه في مساحة الاسم المحلية أو العامة (حتى لو تم توفير اسم غير فارغ).ثم تستخدم عضوًا في تلك الفئة كمتغير تكرار لا يمكن الوصول إليه نظرًا لأن الفئة التي ينتمي إليها لا يمكن الوصول إليها.

#Return first n items of the iterable as a list
list(itertools.islice(iterable, n))

http://docs.python.org/2/library/itertools. أتش تي أم أل

وماذا عن:

while range(some_number):
    #do something
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top