سؤال

أنا معجب كبير ببايثون ل... بناء جملة آخر - من المثير للدهشة عدد المرات التي يتم تطبيقها فيها، ومدى فعاليتها في تبسيط التعليمات البرمجية.

ومع ذلك، لم أكتشف طريقة جيدة لاستخدامه في المولد، على سبيل المثال:

def iterate(i):
    for value in i:
        yield value
    else:
        print 'i is empty'

في المثال أعلاه، أود print بيان ليتم تنفيذه فقط إذا i فارغ.ولكن كما else يحترم فقط break و return, ، يتم تنفيذه دائمًا، بغض النظر عن طوله i.

إذا كان من المستحيل استخدامها for...else بهذه الطريقة، ما هو أفضل نهج لهذا الأمر print يتم تنفيذ البيان فقط عندما لا يتم الحصول على شيء؟

هل كانت مفيدة؟

المحلول

أنت كسر تعريف مولد، والتي ينبغي رمي استثناء StopIteration عند التكرار كاملة (والتي يتم التعامل معها تلقائيا باستخدام عبارة إرجاع في وظيفة مولد)

وهكذا:

def iterate(i):
    for value in i:
        yield value
    return

وأفضل للسماح رمز الدعوة التعامل مع حالة مكرر فارغ:

count = 0
for value in iterate(range([])):
    print value
    count += 1
else:
    if count == 0:
        print "list was empty"

قد يكون وسيلة نظافة للقيام بما سبق، ولكن هذا يجب أن تعمل بشكل جيد، ولا تندرج في أي من نزلات 'معاملة مكرر مثل قائمة "الفخاخ أدناه.

نصائح أخرى

وهناك طرق عدة القيام بذلك. هل يمكن دائما استخدام Iterator مباشرة:

def iterate(i):
    try:
        i_iter = iter(i)
        next = i_iter.next()
    except StopIteration:
        print 'i is empty'
        return

    while True:
        yield next
        next = i_iter.next()

ولكن إذا كنت تعرف المزيد عن ما يمكن توقعه من i حجة، يمكنك أن تكون أكثر إيجازا:

def iterate(i):
    if i:  # or if len(i) == 0
        for next in i:
            yield next
    else:
        print 'i is empty'
        raise StopIteration()

وتلخيص بعض الإجابات السابقة، فإنه يمكن حلها مثل هذا:

def iterate(i):
    empty = True
    for value in i:
        yield value
        empty = False

    if empty:
        print "empty"

وحتى لا يكون هناك حقا أي "آخر" شرط المعنية.

كما لاحظت ، for..else يكتشف فقط أ break.لذلك فهو قابل للتطبيق فقط عندما تبحث عن شيء ما وبعد ذلك قف.

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

سواءً كان المولد أم لا، فأنت تحتاج حقًا إلى قيمة منطقية، كما هو الحال في حل Ber.

<اقتباس فقرة>   <اقتباس فقرة>     

وإذا كان من المستحيل أن تستخدم ل... آخر بهذه الطريقة، ما هي أفضل طريقة لذلك بحيث يتم تنفيذ العبارة الطباعة فقط عند تسفر عن شيء؟

  

والحد الأقصى أستطيع أن أفكر في:


>>> empty = True
>>> for i in [1,2]:
...     empty = False
... if empty:
...     print 'empty'
...
>>>
>>>
>>> empty = True
>>> for i in []:
...     empty = False
... if empty:
...    print 'empty'
...
empty
>>>

وماذا عن بسيط لو-آخر؟

def iterate(i):
    if len(i) == 0: print 'i is empty'
    else:
        for value in i:
            yield value
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top