python - صيغة فهم قائمة متداخلة متقدمة



syntax scope (3)

التوسيع على إجابة لي ريان قليلاً:

شيء = (x لـ x في النطاق (10) إذا كانت x٪ 2 == i لـ i في النطاق (2))

ما يعادل:

def _gen1():
    for x in range(10):
        if x%2 == i:
            for i in range(2):
                yield x
something = _gen1()

في حين أن الإصدار بين قوسين يساوي:

def _gen1():
    def _gen2():
        for x in range(10):
            if x%2 == i:
                yield x

    for i in range(2):
        yield _gen2()
something = _gen1()

هذا بالفعل يعطي المولدين:

[<generator object <genexpr> at 0x02A0A968>, <generator object <genexpr> at 0x02A0A990>]

لسوء الحظ ، فإن المولدات التي تنتجها غير مستقرة إلى حد ما حيث يعتمد الإنتاج على طريقة استهلاكك لها:

>>> gens = ((x for x in range(10) if x%2==i) for i in range(2))
>>> for g in gens:
        print(list(g))

[0, 2, 4, 6, 8]
[1, 3, 5, 7, 9]
>>> gens = ((x for x in range(10) if x%2==i) for i in range(2))
>>> for g in list(gens):
        print(list(g))

[1, 3, 5, 7, 9]
[1, 3, 5, 7, 9]

نصيحتي هي كتابة وظائف المولد بالكامل: أعتقد أن محاولة إجراء الفحص الصحيح على i دون القيام بذلك قد تكون مستحيلة.

https://code.i-harness.com

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

كنت أحاول بشكل أساسي كتابة مولد ينتج مولدات كهربائية. سيبدو المولد البسيط الذي يستخدم فهم القائمة كالتالي:

(x for x in range(10) if x%2==0) # generates all even integers in range(10)

ما كنت أحاول القيام به هو أن أكتب مولدًا ينتج مولدين - أولهما توليد الأرقام الزوجية في النطاق (10) والثاني أنتج الأرقام الفردية في المدى (10). لهذا ، فعلت:

>>> (x for x in range(10) if x%2==i for i in range(2))
<generator object <genexpr> at 0x7f6b90948f00>

>>> for i in g.next(): print i
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> g = (x for x in range(10) if x%2==i for i in range(2))
>>> g
<generator object <genexpr> at 0x7f6b90969730>
>>> g.next()
Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <genexpr>
    UnboundLocalError: local variable 'i' referenced before assignment

لا أفهم لماذا يتم الإشارة إلى "أنا" قبل التعيين

اعتقدت أنه ربما كان هناك علاقة مع i in range(2) ، لذلك فعلت:

>>> g = (x for x in range(10) if x%2==i for i in [0.1])
>>> g
<generator object <genexpr> at 0x7f6b90948f00>
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment

لم يكن هذا منطقيًا بالنسبة لي ، لذلك أعتقد أنه من الأفضل تجربة شيء بسيط أولاً. لذا عدت إلى القوائم وحاولت:

>>> [x for x in range(10) if x%2==i for i in range(2)]
[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]

والتي توقعت أن تكون هي نفسها:

>>> l = []
>>> for i in range(2):
...     for x in range(10):
...             if x%2==i:
...                     l.append(x)
... 
>>> l
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9] # so where is my list comprehension malformed?

ولكن عندما جربتها على حدس ، كان هذا:

>>> [[x for x in range(10) if x%2==i] for i in range(2)]
[[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] # so nested lists in nested list comprehension somehow affect the scope of if statements? :S

لذلك اعتقدت أنه قد يكون مشكلة مع مستوى النطاق if يعمل في البيان. لذلك حاولت ذلك:

>>> [x for x in range(10) for i in range(2) if x%2==i]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

والآن أنا في حيرة من أمري. يمكن للشخص يرجى توضيح هذا السلوك. لا أفهم لماذا تبدو مكونات القائمة الخاصة بي مشوهة ، ولا أفهم كيف يعمل فحص نطاق if العبارات صحيحة.

ملاحظة: في حين يثبت قراءة السؤال ، أدركت أن هذا يبدو قليلا مثل سؤال الواجب المنزلي - فهو ليس كذلك.


الكذب لديه الجواب على السؤال النحوي. اقتراح: لا تدخل أشياء كثيرة في جسم المولد. وظيفة أكثر قابلية للقراءة.

def make_generator(modulus):
    return (x for x in range(10) if x % 2 == modulus)
g = (make_generator(i) for i in range(2))

يؤدي المكافئ الذي يقدمه Lie Ryan إلى الحلقة التالية ، والتي يبدو أنها تعمل بشكل جيد:

[x for i in range(2) for x in range(10) if i == x%2]

المخرجات

[0, 2, 4, 6, 8, 1, 3, 5, 7, 9]




list-comprehension