Simpler way to create dictionary of separate variables?

前端 未结 27 1916
名媛妹妹
名媛妹妹 2020-11-22 02:42

I would like to be able to get the name of a variable as a string but I don\'t know if Python has that much introspection capabilities. Something like:

>&         


        
相关标签:
27条回答
  • 2020-11-22 03:11

    This is a hack. It will not work on all Python implementations distributions (in particular, those that do not have traceback.extract_stack.)

    import traceback
    
    def make_dict(*expr):
        (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
        begin=text.find('make_dict(')+len('make_dict(')
        end=text.find(')',begin)
        text=[name.strip() for name in text[begin:end].split(',')]
        return dict(zip(text,expr))
    
    bar=True
    foo=False
    print(make_dict(bar,foo))
    # {'foo': False, 'bar': True}
    

    Note that this hack is fragile:

    make_dict(bar,
              foo)
    

    (calling make_dict on 2 lines) will not work.

    Instead of trying to generate the dict out of the values foo and bar, it would be much more Pythonic to generate the dict out of the string variable names 'foo' and 'bar':

    dict([(name,locals()[name]) for name in ('foo','bar')])
    
    0 讨论(0)
  • 2020-11-22 03:13

    I've wanted to do this quite a lot. This hack is very similar to rlotun's suggestion, but it's a one-liner, which is important to me:

    blah = 1
    blah_name = [ k for k,v in locals().iteritems() if v is blah][0]
    

    Python 3+

    blah = 1
    blah_name = [ k for k,v in locals().items() if v is blah][0]
    
    0 讨论(0)
  • 2020-11-22 03:13

    In python 3 this is easy

    myVariable = 5
    for v in locals():
      if id(v) == id("myVariable"):
        print(v, locals()[v])
    

    this will print:

    myVariable 5

    0 讨论(0)
  • 2020-11-22 03:14

    As unwind said, this isn't really something you do in Python - variables are actually name mappings to objects.

    However, here's one way to try and do it:

     >>> a = 1
     >>> for k, v in list(locals().iteritems()):
             if v is a:
                 a_as_str = k
     >>> a_as_str
     a
     >>> type(a_as_str)
     'str'
    
    0 讨论(0)
  • 2020-11-22 03:14

    Most objects don't have a __name__ attribute. (Classes, functions, and modules do; any more builtin types that have one?)

    What else would you expect for print(my_var.__name__) other than print("my_var")? Can you simply use the string directly?

    You could "slice" a dict:

    def dict_slice(D, keys, default=None):
      return dict((k, D.get(k, default)) for k in keys)
    
    print dict_slice(locals(), ["foo", "bar"])
    # or use set literal syntax if you have a recent enough version:
    print dict_slice(locals(), {"foo", "bar"})
    

    Alternatively:

    throw = object()  # sentinel
    def dict_slice(D, keys, default=throw):
      def get(k):
        v = D.get(k, throw)
        if v is not throw:
          return v
        if default is throw:
          raise KeyError(k)
        return default
      return dict((k, get(k)) for k in keys)
    
    0 讨论(0)
  • 2020-11-22 03:15

    I wrote the package sorcery to do this kind of magic robustly. You can write:

    from sorcery import dict_of
    
    my_dict = dict_of(foo, bar)
    
    0 讨论(0)
提交回复
热议问题