Oddity in 2.4 with eval('None')

Discussion in 'Python' started by Leif K-Brooks, Dec 20, 2004.

  1. In Python 2.4, although None can't be directly assigned to,
    globals()['None'] can still be; however, that won't change the value of
    the expression "None" in ordinary statements. Except with the eval
    function, it seems:

    Python 2.4 (#2, Dec 3 2004, 17:59:05)
    [GCC 3.3.5 (Debian 1:3.3.5-2)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> print None

    None
    >>> print eval('None')

    None
    >>> globals()['None'] = "spam"
    >>> print None

    None
    >>> print eval('None')

    spam

    I don't really mind this weird behavior; I'm just curious about it. Does
    anyone know what might be going on in Python's internals to cause the
    difference between "print None" and "print eval('None')"?
    Leif K-Brooks, Dec 20, 2004
    #1
    1. Advertising

  2. Leif K-Brooks

    Steve Holden Guest

    Leif K-Brooks wrote:

    > In Python 2.4, although None can't be directly assigned to,
    > globals()['None'] can still be; however, that won't change the value of
    > the expression "None" in ordinary statements. Except with the eval
    > function, it seems:
    >
    > Python 2.4 (#2, Dec 3 2004, 17:59:05)
    > [GCC 3.3.5 (Debian 1:3.3.5-2)] on linux2
    > Type "help", "copyright", "credits" or "license" for more information.
    > >>> print None

    > None
    > >>> print eval('None')

    > None
    > >>> globals()['None'] = "spam"
    > >>> print None

    > None
    > >>> print eval('None')

    > spam
    >
    > I don't really mind this weird behavior; I'm just curious about it. Does
    > anyone know what might be going on in Python's internals to cause the
    > difference between "print None" and "print eval('None')"?


    Yes. "print eval('None')" is printing the value of None as defined in
    your module's global namespace:

    Python 2.4 (#1, Dec 4 2004, 20:10:33)
    [GCC 3.3.3 (cygwin special)] on cygwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> globals()['None'] = "FooBar"
    >>> print sys.modules["__main__"].None

    FooBar
    >>> print __builtins__.None

    None
    >>> print eval("__builtins__.None")

    None >>>

    regards
    Steve
    --
    Steve Holden http://www.holdenweb.com/
    Python Web Programming http://pydish.holdenweb.com/
    Holden Web LLC +1 703 861 4237 +1 800 494 3119
    Steve Holden, Dec 20, 2004
    #2
    1. Advertising

  3. Leif K-Brooks

    M.E.Farmer Guest

    Python 2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> dir()

    ['__builtins__', '__doc__', '__name__', 'shell']
    >>> globals()['None']

    Traceback (most recent call last):
    File "<input>", line 1, in ?
    KeyError: None
    >>> print None

    None
    >>> print eval('None')

    None
    >>> globals()['None']='wassabi'
    >>> print None

    wassabi
    >>> print eval('None')

    wassabi
    >>> dir()

    ['None', '__builtins__', '__doc__', '__name__', 'shell']
    >>>


    I think you are seeing two things and I admit I was confused a bit too.
    None is becoming a constant and this is the first step. That is why you
    see diffrent results than mine. Also notyice that None didn't exist in
    your lnamespace till you defined it then you see all your trouble
    start.Shadowing builtins and semi-constants are a bad thing
    M.E.Farmer
    M.E.Farmer, Dec 20, 2004
    #3
  4. Steve Holden wrote:
    > Yes. "print eval('None')" is printing the value of None as defined in
    > your module's global namespace:


    Right, but why? The expression "None" doesn't worry about the global
    namespace when used in normal code; why does it when used in eval()ed code?
    Leif K-Brooks, Dec 20, 2004
    #4
  5. Leif K-Brooks

    Steve Holden Guest

    Leif K-Brooks wrote:

    > Steve Holden wrote:
    >
    >> Yes. "print eval('None')" is printing the value of None as defined in
    >> your module's global namespace:

    >
    >
    > Right, but why? The expression "None" doesn't worry about the global
    > namespace when used in normal code; why does it when used in eval()ed code?


    I have no idea why. Given that

    >>> eval("globals()['__builtins__'].globals().keys()")

    ['None', '__builtins__', '__file__', 'sys', '__name__', '__doc__']

    it's beginning to smell a bit like a buglet.

    regards
    Steve
    --
    Steve Holden http://www.holdenweb.com/
    Python Web Programming http://pydish.holdenweb.com/
    Holden Web LLC +1 703 861 4237 +1 800 494 3119
    Steve Holden, Dec 20, 2004
    #5
  6. Leif K-Brooks wrote

    >> Yes. "print eval('None')" is printing the value of None as defined in your module's global
    >> namespace:

    >
    > Right, but why? The expression "None" doesn't worry about the global namespace when used in normal
    > code; why does it when used in eval()ed code?


    from what I can tell, the mapping of the None symbol to a constant is done
    in the peephole optimizer, which doesn't seem to be used when compiling
    expressions.

    in 2.4:

    >>> dis.dis(compile("None", "", "exec"))

    1 0 LOAD_CONST 0 (None)
    3 POP_TOP
    ...
    >>> dis.dis(compile("None", "", "eval"))

    0 0 LOAD_NAME 0 (None)
    3 RETURN_VALUE

    in 2.3:

    >>> dis.dis(compile("None", "", "exec"))

    1 0 LOAD_NAME 0 (None)
    3 POP_TOP
    ...
    >>> dis.dis(compile("None", "", "eval"))

    0 0 LOAD_NAME 0 (None)
    3 RETURN_VALUE

    </F>
    Fredrik Lundh, Dec 20, 2004
    #6
  7. "Leif K-Brooks" <>
    > In Python 2.4, although None can't be directly assigned to,
    > globals()['None'] can still be; however, that won't change the value of
    > the expression "None" in ordinary statements. Except with the eval
    > function, it seems:
    >
    > Python 2.4 (#2, Dec 3 2004, 17:59:05)
    > [GCC 3.3.5 (Debian 1:3.3.5-2)] on linux2
    > Type "help", "copyright", "credits" or "license" for more information.
    > >>> print None

    > None
    > >>> print eval('None')

    > None
    > >>> globals()['None'] = "spam"
    > >>> print None

    > None
    > >>> print eval('None')

    > spam
    >
    > I don't really mind this weird behavior; I'm just curious about it. Does
    > anyone know what might be going on in Python's internals to cause the
    > difference between "print None" and "print eval('None')"?


    It is a nuance of how None is being made constant.

    For backwards compatability, None still has to be in the globals dictionary.
    Like all entries in the globals dictionary, you can change it if you try hard
    enough (which you did).

    For Py2.4, whenever bytecode is generated for a code object, references to
    "None" in the globals dictionary are bypassed and replaced with a constant
    reference to Py_None, the one, true, singleton instance of None. That will
    occur even if you've mucked with None entry in the globals dictionary.

    Bytecode for eval() doesn't go through the bytecode optimizer so its dictionary
    lookup is retained (producing the effect in your example).

    To have made None a literal constant would have been a much more radical step.
    Py2.4 simulates this and gives you the real benefit being sought, faster
    function execution, without having incurred the costs of having a new literal.

    It's possible to fool the simulation, but who cares.


    Raymond Hettinger
    Raymond Hettinger, Dec 20, 2004
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David Freeman
    Replies:
    8
    Views:
    7,624
    tcena9
    Feb 16, 2011
  2. length power
    Replies:
    2
    Views:
    69
    Rustom Mody
    Apr 10, 2014
  3. Skip Montanaro
    Replies:
    0
    Views:
    51
    Skip Montanaro
    Apr 10, 2014
  4. Johannes Schneider

    Re: why i have the output of [None, None, None]

    Johannes Schneider, Apr 10, 2014, in forum: Python
    Replies:
    0
    Views:
    46
    Johannes Schneider
    Apr 10, 2014
  5. Terry Reedy
    Replies:
    0
    Views:
    55
    Terry Reedy
    Apr 10, 2014
Loading...

Share This Page