Problem/bug with class definition inside function definition

Alexey Muranov alexey.muranov at gmail.com
Tue May 8 03:55:00 EDT 2018


Sorry, i was confused.  I would say that this mostly works as expected, 
though the difference between

    x = 42

    class C:
        x = x  # Works

and

    def f2(a):
        class D:
            a = a  # Does not work <<<<<
        return D

is still surprising to me.

Otherwise, probably the solution with

    def f(a):
        _a = a
        class D:
            a = _a
        return D

is good enough, if Python does not allow to refer "simultaneously" to 
variables from different scopes if they have the same name.

Alexey.


On Tue, 8 May, 2018 at 12:21 AM, Alexey Muranov 
<alexey.muranov at gmail.com> wrote:
> To be more exact, i do see a few workarounds, for example:
> 
> 
>    def f4(a):
>        b = a
>        class D:
>            a = b  # Works
>        return D
> 
> But this is not what i was hoping for.
> 
> Alexey.
> 
> On Tue, 8 May, 2018 at 12:02 AM, Alexey Muranov 
> <alexey.muranov at gmail.com> wrote:
>> I have discovered the following bug or problem: it looks like i am 
>> forced to choose different names for class attributes and function 
>> arguments, and i see no workaround.  Am i missing some special 
>> syntax feature ?
>> 
>> Alexey.
>> 
>> ---
>> x = 42
>> 
>> class C1:
>>    y = x  # Works
>> 
>> class C2:
>>    x = x  # Works
>> 
>> # ---
>> def f1(a):
>>    class D:
>>        b = a  # Works
>>    return D
>> 
>> def f2(a):
>>    class D:
>>        a = a  # Does not work <<<<<
>>    return D
>> 
>> def f3(a):
>>    class D:
>>        nonlocal a
>>        a = a  # Does not work either <<<<<
>>    return D
>> 
>> # ---
>> def g1(a):
>>    def h():
>>        b = a  # Works
>>        return b
>>    return h
>> 
>> def g2(a):
>>    def h():
>>        a = a  # Does not work (as expected)
>>        return a
>>    return h
>> 
>> def g3(a):
>>    def h():
>>        nonlocal a
>>        a = a  # Works
>>        return a
>>    return h
>> 
>> # ---
>> if __name__ == "__main__":
>>    assert C1.y == 42
>>    assert C2.x == 42
>> 
>>    assert f1(13).b == 13
>> 
>>    try:
>>        f2(13)  # NameError
>>    except NameError:
>>        pass
>>    except Exception as e:
>>        raise Exception( 'Unexpected exception raised: '
>>                         '{}'.format(type(e).__name__) )
>>    else:
>>        raise Exception('No exception')
>> 
>>    try:
>>        f3(13).a  # AttributeError
>>    except AttributeError:
>>        pass
>>    except Exception as e:
>>        raise Exception( 'Unexpected exception raised: '
>>                         '{}'.format(type(e).__name__) )
>>    else:
>>        raise Exception('No exception')
>> 
>>    assert g1(13)() == 13
>> 
>>    try:
>>        g2(13)()  # UnboundLocalError
>>    except UnboundLocalError:
>>        pass
>>    except Exception as e:
>>        raise Exception( 'Unexpected exception raised: '
>>                         '{}'.format(type(e).__name__) )
>>    else:
>>        raise Exception('No exception')
>> 
>>    assert g3(13)() == 13
>> 
> 




More information about the Python-list mailing list