Getting current variable name

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

    #1

    Getting current variable name

    Hi all,
    I followed the mails entitled 'How to turn a variable name into a
    string?' in march 2005 posts as I have a similar problem.

    I have to get some list variable names at some point in my program. So
    I ended up looking into globals() to get them with a small function like
    this:

    #!/usr/bin/python

    l1 = ['r', 'r', 't']
    l2 = ['r', 't', 't']
    l3 = ['t', 't', 't'] # Two equivalent lists but...
    l4 = ['t', 't', 't'] # with different names

    def nameofObj(obj):
    # print locals()
    globdict = globals()
    var = globals().keys( )
    for i in var :
    if globdict[i] == obj:
    print i


    print '-'*20 ,'\n'
    nameofObj(l1)

    print '-'*20 ,'\n'
    map(nameofObj, [l1, l2, l3, l4])

    --------------------------------------------------------------------
    If you try this, with 2 equivalent lists
    (here l3 and l4 when using map) the function will return both
    possibilities l3 and l4 which I understand.
    So this solution is limitated to unique lists, unfortunately I do have
    equivalent lists in my case...

    The problem comes from the fact that locals() and globals() have
    in common their values but not the keys which then can't be tested.

    The only solution I see would be to link the list and its name (in
    a dictionary for instance) but that does not sound elegant to me?
    If you guys can help a newbie...

    Thank you
    --
    ------------------------------------------------------------------
    | Patrick LADAM | |
    | Laboratoire CSSB | THE BIG BANG THEORY: |
    | UFR SMBH | |
    | 74 rue Marcel Cachin | In the begining there was |
    | 93017 Bobigny CEDEX | nothing at all. |
    | >>> NEW e-mail: <<< | |
    | ladam@smbh.smbh .univ-paris13.fr | Then, it exploded... |
    | Tel: 01 48 38 77 26 / 76 85 | |
    | Fax: 01 48 38 77 77 | |
    ------------------------------------------------------------------




  • Daniel Dittmar

    #2
    Re: Getting current variable name

    pl wrote:[color=blue]
    > I have to get some list variable names at some point in my program. So
    > I ended up looking into globals() to get them with a small function like
    > this:[/color]
    [...][color=blue]
    > var = globals().keys( )
    > for i in var :
    > if globdict[i] == obj:
    > print i[/color]

    Use 'is' instead of '=='. This will return true if the arguments are the
    same object:[color=blue][color=green][color=darkred]
    >>> l1 = [1, 2, 3]
    >>> l2 = [1, 2, 3]
    >>> l1 == l2[/color][/color][/color]
    True[color=blue][color=green][color=darkred]
    >>> l1 is l2[/color][/color][/color]
    False

    Daniel

    Comment

    • Steven Bethard

      #3
      Re: Getting current variable name

      pl wrote:[color=blue]
      > I followed the mails entitled 'How to turn a variable name into a
      > string?' in march 2005 posts as I have a similar problem.
      >
      > I have to get some list variable names at some point in my program. So
      > I ended up looking into globals() to get them with a small function like
      > this:
      >
      > #!/usr/bin/python
      >
      > l1 = ['r', 'r', 't']
      > l2 = ['r', 't', 't']
      > l3 = ['t', 't', 't'] # Two equivalent lists but...
      > l4 = ['t', 't', 't'] # with different names
      >
      > def nameofObj(obj):
      > # print locals()
      > globdict = globals()
      > var = globals().keys( )
      > for i in var :
      > if globdict[i] == obj:
      > print i
      >
      >
      > print '-'*20 ,'\n'
      > nameofObj(l1)
      >
      > print '-'*20 ,'\n'
      > map(nameofObj, [l1, l2, l3, l4])[/color]

      What is the problem you're trying to solve here? Looking up the names
      of an object is not usually something you want to do. If you provide a
      little more detail on your use case, we might be able to help you
      refactor this code.

      STeVe

      Comment

      • Ron

        #4
        Re: Getting current variable name

        pl wrote:[color=blue]
        > Hi all,
        > I followed the mails entitled 'How to turn a variable name into a
        > string?' in march 2005 posts as I have a similar problem.[/color]

        Use the locals() function instead of globals().

        Thanks by the way, I was wondering how to do this also, your post, and
        Daniel pointing out 'is', helped me work this out. There should be an
        easier way that doesn't require stepping though the name list.

        This doesn't use lists in the same way, but I think it answers your
        question.

        def getvinfo(vars, v):
        """
        vars is locals()
        v is [varable]
        Use an one item list to pass single varables by reference.
        """
        for n in vars.keys():
        if vars[n] is v[0]:
        return n, v[0], type(v[0])

        a = 101
        b = 2.3
        c = True

        print getvinfo(locals (), [a])
        print getvinfo(locals (), [b])
        print getvinfo(locals (), [c])
        [color=blue][color=green][color=darkred]
        >>>[/color][/color][/color]
        ('a', 101, <type 'int'>)
        ('b', 2.2999999999999 998, <type 'float'>)
        ('c', True, <type 'bool'>)


        This could be useful for printing error messages and debugging info.

        Ronald Adam

        Comment

        • Jeff Shannon

          #5
          Re: Getting current variable name

          Ron wrote:
          [color=blue]
          > def getvinfo(vars, v):
          > """
          > vars is locals()
          > v is [varable]
          > Use an one item list to pass single varables by reference.
          > """
          > for n in vars.keys():
          > if vars[n] is v[0]:
          > return n, v[0], type(v[0])
          >
          > a = 101
          > b = 2.3
          > c = True
          >
          > print getvinfo(locals (), [a])
          > print getvinfo(locals (), [b])
          > print getvinfo(locals (), [c])
          >[color=green][color=darkred]
          > >>>[/color][/color]
          > ('a', 101, <type 'int'>)
          > ('b', 2.2999999999999 998, <type 'float'>)
          > ('c', True, <type 'bool'>)[/color]

          Are you sure that you really need that single-element list?
          [color=blue][color=green][color=darkred]
          >>> def getvinfo2(vars, v):[/color][/color][/color]
          .... for n in vars.keys():
          .... if vars[n] is v:
          .... return n, v, type(v)
          ....[color=blue][color=green][color=darkred]
          >>> getvinfo2(local s(), a)[/color][/color][/color]
          ('a', 1, <type 'int'>)[color=blue][color=green][color=darkred]
          >>> getvinfo2(local s(), b)[/color][/color][/color]
          ('b', 2.2999999999999 998, <type 'float'>)[color=blue][color=green][color=darkred]
          >>>[/color][/color][/color]

          Now, making that second parameter a list would enable you to do this
          for multiple local names with a single call, but getvinfo() doesn't
          try to do that...

          Don't forget, in Python, all names are references. You only have to
          be careful when you start re-binding names...

          Jeff Shannon

          Comment

          • Lonnie Princehouse

            #6
            Re: Getting current variable name

            > There should be an easier way that doesn't require stepping though
            the name list.

            Trying to find names bound to a particular object is a /very/ strange
            thing to want to do in Python. If this is for anything more than
            debugging diagnostics, it's probably better to use a dictionary
            explicitly for your variables and not muck around with global or local
            namespace.

            Comment

            • Ron

              #7
              Re: Getting current variable name

              Jeff Shannon wrote:[color=blue]
              >
              > Are you sure that you really need that single-element list?[/color]

              No I'm not sure, I thought I found a concdition where it made a
              difference while playing with it, but I don't recall just what
              circumstance it was?
              [color=blue]
              > Don't forget, in Python, all names are references. You only have to be
              > careful when you start re-binding names...[/color]

              Since more than one name can bind to an object, this would be better.


              def getvinfo( vars, v ):
              names = []
              for n in vars.keys():
              if vars[n] is v:
              names.append(n)
              return names, v, type(v)

              a = [2]
              b = [2]
              c = b

              print getvinfo( locals(), a )
              print getvinfo( locals(), b )
              print getvinfo( locals(), c )
              [color=blue][color=green][color=darkred]
              >>>[/color][/color][/color]
              (['a'], [2], <type 'list'>)
              (['b', 'c'], [2], <type 'list'>)
              (['b', 'c'], [2], <type 'list'>)[color=blue][color=green][color=darkred]
              >>>[/color][/color][/color]













              Comment

              • Steve

                #8
                Things you shouldn't do

                All names have been removed to protect the guilty :-)

                In an earlier post, I read a piece of code:
                [color=blue][color=green][color=darkred]
                >>> l1 = [1, 2, 3]
                >>> l2 = [1, 2, 3]
                >>> l1 == l2[/color][/color][/color]
                True

                I immediately gave a double-take: 11 equals 12? What
                gives? Can you re-bind literals in Python???
                [color=blue][color=green][color=darkred]
                >>> 11 = [1, 2, 3][/color][/color][/color]
                SyntaxError: can't assign to literal

                And then it hit me. That wasn't eleven and twelve, the
                variable names were lowercase L with the digits one and
                two appended.

                Imagine running a long piece of code on some test data
                and finding an off-by-one bug which you think is on the
                line "myvalue = something + l1". You change the eleven
                to 12 and now the code works on your test data but not
                for anything else.

                If you have access to a syntax-aware editor, it will
                help avoid such problems, but better to avoid them in
                the first place. You might be reading code printed in
                black and white on dead tree one day.

                Lesson the first: remember that in many fonts, zero and
                capital O are identical, as are lowercase L and 1 and
                sometimes even uppercase I. Avoid using names which can
                be easily confused for literals or for each other.

                What are some of other people's favourite tips for
                avoiding bugs in the first place, as opposed to finding
                them once you know they are there?


                --
                Steven


                Comment

                • Paul McGuire

                  #9
                  Re: Things you shouldn't do

                  This struck me also when I first saw this post. It reminded me of a
                  body of code I inherited at a former job, that I had to help untangle.
                  The code was filled with two key variables: t_1 and t_l. Printing out
                  the source in a Courier font made these two vars completely
                  indistinguishab le, and it took a while to realize that there even were
                  two different vars. After globally replacing them with t_first and
                  t_last, things became a lot clearer!

                  -- Paul

                  Comment

                  • Andrew Dalke

                    #10
                    Re: Things you shouldn't do

                    Steve wrote:[color=blue]
                    > [an anecdote on distinguishing l1 and 11][/color]
                    [color=blue]
                    > What are some of other people's favourite tips for
                    > avoiding bugs in the first place, as opposed to finding
                    > them once you know they are there?[/color]

                    There's a good book on this topic - Writing Solid Code.

                    Andrew
                    dalke@dalkescie ntific.com

                    Comment

                    • Eric Brunel

                      #11
                      Re: Things you shouldn't do

                      On Wed, 30 Mar 2005 07:02:57 GMT, Andrew Dalke <dalke@dalkesci entific.com> wrote:
                      [color=blue]
                      > Steve wrote:[color=green]
                      >> [an anecdote on distinguishing l1 and 11][/color]
                      >[color=green]
                      >> What are some of other people's favourite tips for
                      >> avoiding bugs in the first place, as opposed to finding
                      >> them once you know they are there?[/color]
                      >
                      > There's a good book on this topic - Writing Solid Code.[/color]

                      And there's an excellent website showing what *not* to do:


                      The OP's point is paragraph 11 in the "Camouflage " section.
                      --
                      python -c 'print "".join([chr(154 - ord(c)) for c in "U(17zX(%,5.z^5 (17l8(%,5.Z*(93-965$l7+-"])'

                      Comment

                      • Richie Hindle

                        #12
                        Re: Things you shouldn't do


                        [Steven][color=blue]
                        > If you have access to a syntax-aware editor, it will
                        > help avoid such problems[/color]

                        Seconded. Here's my favourite real-world example of where the lack of
                        syntax colouring cost several man-days of work (though this couldn't
                        happen with modern C compilers):

                        extern void get_s(short* s);

                        void f()
                        {
                        int i; /* An integer to do something /*
                        short s; /* A short to do something */

                        get_s(&s);
                        /* Do something with s */
                        }

                        --
                        Richie Hindle
                        richie@entrian. com

                        Comment

                        • Paul McGuire

                          #13
                          Re: Things you shouldn't do

                          Here's another real world example, although it was in C:

                          char* ptr;
                          assert( ptr = malloc( memsize ); )

                          Of course, this worked when built in debug, but it took a while to
                          track down why it wasn't working in the release build (the assert()'s
                          were stripped out in the release builds, so ptr didn't allocate any
                          memory). Unfortunately, the runtime failure happened in an entirely
                          different part of the code, since ptr wasn't initialized to null, so
                          this particular routine just merrily stomped on whatever memory address
                          happened to initialize in ptr.

                          -- Paul

                          Comment

                          • Thomas Bartkus

                            #14
                            Re: Things you shouldn't do

                            "Steve" <dippyd@yahoo.c om> wrote in message
                            news:424A2080.4 080800@yahoo.co m...
                            <snip>[color=blue]
                            > What are some of other people's favourite tips for
                            > avoiding bugs in the first place, as opposed to finding
                            > them once you know they are there?
                            >[/color]
                            Fonts with slashed zeros and serifs.

                            -Tom



                            Comment

                            • Greg Ewing

                              #15
                              Re: Things you shouldn't do

                              Paul McGuire wrote:[color=blue]
                              > The code was filled with two key variables: t_1 and t_l. Printing out
                              > the source in a Courier font made these two vars completely
                              > indistinguishab le,[/color]

                              Are you sure it was Courier? I'm looking at it now
                              in Courier, and they are different, although very
                              similar.

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

                              Comment

                              Working...