eval function not working how i want it dag namn

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • robcarlton

    eval function not working how i want it dag namn

    hi everybody
    I've written this function to make a list of all of an objects
    attributes and methods (not for any reason, I'm just learning)

    def list_members(ob j)
    l = dir(obj)
    return map(lambda x : eval('obj.'+x), l)

    but I get an error saying that obj isn't defined. As I understand it
    eval has access to the current local namespace, which does contain
    object, so I'm not sure whats going wrong.

    ps Im sure there are better ways of doing the above which doesn't call
    the eval function, and while I'd be glad to know what it is, I'd still
    like to understand why my way isnt working

    thanks

  • Michael Hoffman

    #2
    Re: eval function not working how i want it dag namn

    robcarlton wrote:
    [color=blue]
    > I've written this function to make a list of all of an objects
    > attributes and methods (not for any reason, I'm just learning)
    >
    > def list_members(ob j)
    > l = dir(obj)
    > return map(lambda x : eval('obj.'+x), l)[/color]

    That works fine for me with Python 2.4.

    This is the best way to do it:

    def list_members(ob j):
    return [getattr(obj, name) for name in dir(obj)]

    Although personally I would prefer to have this information in dict
    form, so i'd use:

    return dict((name, getattr(obj, name)) for name in dir(obj))

    For objects defined in CPython, you can use obj.__dict__, but this is
    somewhat hacky, and I'd avoid it.
    --
    Michael Hoffman

    Comment

    • Gerald Klix

      #3
      Re: eval function not working how i want it dag namn

      How about using the vars builtin?

      Michael Hoffman schrieb:[color=blue]
      > robcarlton wrote:
      >[color=green]
      >> I've written this function to make a list of all of an objects
      >> attributes and methods (not for any reason, I'm just learning)
      >>
      >> def list_members(ob j)
      >> l = dir(obj)
      >> return map(lambda x : eval('obj.'+x), l)[/color]
      >
      >
      > That works fine for me with Python 2.4.
      >
      > This is the best way to do it:
      >
      > def list_members(ob j):
      > return [getattr(obj, name) for name in dir(obj)]
      >
      > Although personally I would prefer to have this information in dict
      > form, so i'd use:
      >
      > return dict((name, getattr(obj, name)) for name in dir(obj))
      >
      > For objects defined in CPython, you can use obj.__dict__, but this is
      > somewhat hacky, and I'd avoid it.[/color]

      --
      GPG-Key: http://keyserver.veridis.com:11371/search?q=0xA140D634

      Comment

      • Peter Otten

        #4
        Re: eval function not working how i want it dag namn

        robcarlton wrote:
        [color=blue]
        > hi everybody
        > I've written this function to make a list of all of an objects
        > attributes and methods (not for any reason, I'm just learning)
        >
        > def list_members(ob j)
        > l = dir(obj)
        > return map(lambda x : eval('obj.'+x), l)
        >
        > but I get an error saying that obj isn't defined. As I understand it
        > eval has access to the current local namespace, which does contain
        > object, so I'm not sure whats going wrong.
        >
        > ps Im sure there are better ways of doing the above which doesn't call
        > the eval function, and while I'd be glad to know what it is, I'd still
        > like to understand why my way isnt working[/color]

        It would work if obj were in the local namespace like so:
        [color=blue][color=green][color=darkred]
        >>> def f(obj="x"):[/color][/color][/color]
        .... return eval("obj")
        ....[color=blue][color=green][color=darkred]
        >>> f()[/color][/color][/color]
        'x'

        but with the lambda you are introducing a nested namespace.
        [color=blue][color=green][color=darkred]
        >>> def f(obj="x"):[/color][/color][/color]
        .... return (lambda: eval("obj"))()
        ....[color=blue][color=green][color=darkred]
        >>> f()[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<stdin>", line 2, in f
        File "<stdin>", line 2, in <lambda>
        File "<string>", line 0, in ?
        NameError: name 'obj' is not defined

        You are doing the equivalent to
        [color=blue][color=green][color=darkred]
        >>> def f(obj="x"):[/color][/color][/color]
        .... def g(): # no obj in g()'s namespace
        .... return eval("obj")
        .... return g()
        ....[color=blue][color=green][color=darkred]
        >>> f()[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<stdin>", line 4, in f
        File "<stdin>", line 3, in g
        File "<string>", line 0, in ?
        NameError: name 'obj' is not defined

        only in a convoluted way. Let's make f()'s local variable obj visible in
        g(), too:
        [color=blue][color=green][color=darkred]
        >>> def f(obj="x"):[/color][/color][/color]
        .... def g():
        .... obj # now you can see me
        .... return eval("obj")
        .... return g()
        ....[color=blue][color=green][color=darkred]
        >>> f()[/color][/color][/color]
        'x'

        Here's another way that is viable with lambda, too.
        [color=blue][color=green][color=darkred]
        >>> def f(obj="x"):[/color][/color][/color]
        .... return (lambda obj=obj: eval("obj"))()
        ....[color=blue][color=green][color=darkred]
        >>> f()[/color][/color][/color]
        'x'

        I'm sure you can fix your list_members() accordingly. Note that rebinding
        obj between the definition and call of g() will affect the result only in
        the first of the last two examples.

        And now for something completely different:
        [color=blue][color=green][color=darkred]
        >>> def list_members(ob j):[/color][/color][/color]
        .... return [getattr(obj, name) for name in dir(obj)]
        ....[color=blue][color=green][color=darkred]
        >>> import os
        >>> list_members(os )[:5][/color][/color][/color]
        [73, 78, 65, 74, 68][color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]

        Peter

        Comment

        • Peter Otten

          #5
          Re: eval function not working how i want it dag namn

          Michael Hoffman wrote:
          [color=blue][color=green]
          >> def list_members(ob j)
          >>l = dir(obj)
          >>return map(lambda x : eval('obj.'+x), l)[/color]
          >
          > That works fine for me with Python 2.4.[/color]

          Python 2.4 (#6, Jan 30 2005, 11:14:08)
          [GCC 3.3.3 (SuSE Linux)] on linux2
          Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
          >>> def lm(obj):[/color][/color][/color]
          .... l = dir(obj)
          .... return map(lambda x: eval("obj." + x), l)
          ....[color=blue][color=green][color=darkred]
          >>> class X:[/color][/color][/color]
          .... pass
          ....[color=blue][color=green][color=darkred]
          >>> x = X()
          >>> x.question = "Are you sure?"
          >>> lm(x)[/color][/color][/color]
          Traceback (most recent call last):
          File "<stdin>", line 1, in ?
          File "<stdin>", line 3, in lm
          File "<stdin>", line 3, in <lambda>
          File "<string>", line 0, in ?
          NameError: name 'obj' is not defined[color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          Peter

          Comment

          • Michael Hoffman

            #6
            Re: eval function not working how i want it dag namn

            Peter Otten wrote:[color=blue]
            > Michael Hoffman wrote:
            >[color=green][color=darkred]
            >>>def list_members(ob j)
            >>>l = dir(obj)
            >>>return map(lambda x : eval('obj.'+x), l)[/color]
            >>
            >>That works fine for me with Python 2.4.[/color]
            >[color=green][color=darkred]
            >>>>x.questio n = "Are you sure?"[/color][/color][/color]

            I should clarify. It works fine for me when I've already globally
            assigned obj to something else. D'oh!
            --
            Michael Hoffman

            Comment

            • robcarlton

              #7
              Re: eval function not working how i want it dag namn

              thanks. I'll use the getattr function now, and I think I understand
              where I went wrong with eval. I was thinking in Lisp where the lexical
              scope would mean that obj is defined

              Comment

              • Greg Ewing

                #8
                Re: eval function not working how i want it dag namn

                robcarlton wrote:[color=blue]
                > thanks. I'll use the getattr function now, and I think I understand
                > where I went wrong with eval. I was thinking in Lisp where the lexical
                > scope would mean that obj is defined[/color]

                The full story is actually more subtle. The name 'obj'
                *is* accessible from a nested scope if you do something
                like

                def f(obj):
                def g():
                print obj
                g()

                But the bytecode compiler has to do extra work to make
                a name in an intermediate scope accessible to an inner
                scope, and it only does this if it sees a reference to
                the name in the inner scope. In your code, the reference
                is invisible at compile time, so the compiler misses it,
                and the run-time evaluation fails.

                --
                Greg Ewing, Computer Science Dept,
                University of Canterbury,
                Christchurch, New Zealand

                Comment

                Working...