Programing

별도의 변수 사전을 만드는 간단한 방법?

lottogame 2020. 4. 25. 09:47
반응형

별도의 변수 사전을 만드는 간단한 방법?


변수의 이름을 문자열로 얻을 수 있기를 원하지만 파이썬에 많은 내성 기능이 있는지 모르겠습니다. 다음과 같은 것 :

>>> print(my_var.__name__)
'my_var'

변수가 많기 때문에 다음과 같은 사전으로 바꾸고 싶습니다.

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

그러나 나는 그것보다 더 자동적 인 것을 원합니다.

파이썬은이 locals()vars()나는 방법이 생각 때문에.


이 작업을 시도하고 있습니까?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}

unwind가 말했듯이, 이것은 실제로 파이썬에서하는 것이 아닙니다. 변수는 실제로 객체에 대한 이름 매핑입니다.

그러나 시도하고 수행하는 한 가지 방법이 있습니다.

 >>> 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'

나는 이것을 많이하고 싶었다. 이 핵은 rlotun의 제안과 매우 유사하지만 하나의 라이너로 나에게 중요합니다.

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

파이썬 3+

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

이것은 해킹입니다. 모든 Python 구현 배포판 (특히없는 배포본)에서는 작동하지 않습니다 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}

이 핵은 깨지기 쉽습니다.

make_dict(bar,
          foo)

(2 줄에 make_dict를 호출하면) 작동하지 않습니다.

대신의 DICT을 생성하기 위해 노력하는 foobar, 그것은 훨씬 더 파이썬은 문자열의 밖으로 DICT 생성하는 것이다 변수 이름 'foo''bar':

dict([(name,locals()[name]) for name in ('foo','bar')])

실제로는 "변수"가없는 파이썬에서는 불가능합니다. Python에는 이름이 있으며 동일한 객체에 대해 둘 이상의 이름이있을 수 있습니다.


내 문제가이 질문이 왜 유용한 지 설명하는 데 도움이 될 것이며, 답변하는 방법에 대해 좀 더 통찰력을 줄 수도 있습니다. 내 코드의 다양한 변수에 대해 빠른 인라인 헤드 검사를 수행하는 작은 함수를 작성했습니다. 기본적으로 변수 이름, 데이터 유형, 크기 및 기타 속성이 나열되어 있으므로 실수를 신속하게 파악할 수 있습니다. 코드는 간단하다 :

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

따라서 복잡한 사전 / 목록 / 튜플 상황이있는 경우 통역사가 지정한 변수 이름을 반환하도록하는 것이 도움이됩니다. 예를 들어, 여기 이상한 사전이 있습니다.

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

나는 이것을 올바른 장소에 넣었는지 확실하지 않지만 도움이 될 것이라고 생각했습니다. 나는 그것을 희망한다.


이 질문에 대한 답을 바탕으로 깔끔하고 유용한 기능을 작성했습니다. 유용 할 수 있도록 여기에 넣겠습니다.

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

용법:

>> a = 4
>> what(a)
a = 4
>>|

이미 특정 값 목록이 있으면 @S가 설명하는 방식을 발견했습니다. 로트가 최고입니다. 그러나 아래 설명 된 방법은 원하는 경우 변수 이름을 제공 할 필요는 없지만 변수 이름을 제공 할 필요 없이 코드 전체에 추가 된 모든 변수와 클래스를 얻는 데 효과적 입니다. 클래스를 제외하도록 코드를 확장 할 수 있습니다.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

산출:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}

파이썬 3에서는 쉽습니다.

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

이것은 인쇄됩니다 :

myVariable 5


파이썬 3. inspect를 사용하여 호출 로컬 네임 스페이스를 캡처 한 다음 여기에 제시된 아이디어를 사용하십시오. 지적한대로 둘 이상의 답변을 반환 할 수 있습니다.

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass

변수 이름을 읽기 위해 만든 함수는 다음과 같습니다. 더 일반적이며 다른 응용 프로그램에서 사용할 수 있습니다.

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

지정된 질문에 사용하려면

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}

실을 읽을 때 나는 많은 마찰을 보았다. 잘못된 답변을 한 다음 다른 사람이 올바른 답변을 내릴 수있을 정도로 쉽습니다. 어쨌든, 여기 내가 찾은 것이 있습니다.

보낸 사람 : [effbot.org] ( http://effbot.org/zone/python-objects.htm#names )

이름은 약간 다릅니다. 실제로는 객체의 속성이 아니며, 객체 자체는 그 객체가 무엇인지 모릅니다.

객체는 여러 개의 이름을 갖거나 전혀 이름을 가질 수 없습니다.

이름은 네임 스페이스 (예 : 모듈 네임 스페이스, 인스턴스 네임 스페이스, 함수의 로컬 네임 스페이스)에 있습니다.

참고 : 그것은 객체 자체가 무엇이라고 불리는 지 알지 못한다고 말했기 때문에 이것이 단서였습니다. 파이썬 객체는 자기 참조가 아닙니다. 그런 다음 이름은 네임 스페이스에 있습니다. 우리는 이것을 TCL / TK에 있습니다. 아마도 내 대답이 도움이 될 것입니다 (그러나 도움이되었습니다)


    jj = 123
    인쇄 평가 ( " '"+ str (id (jj)) + "'")
    프린트 디렉토리 ()

166707048
[ '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

목록 끝에 'jj'가 있습니다.

코드를 다음과 같이 다시 작성하십시오.


    jj = 123
    인쇄 평가 ( " '"+ str (id (jj)) + "'")
    dir ()에서 x의 경우 :
        프린트 아이디 (eval (x))

161922920
[ '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

이 불쾌한 코드 id는 변수 / 객체 / 무엇이든 당신이 호출하는 호출의 이름입니다.

그래서 거기에 있습니다. 'jj'의 메모리 주소는 전역 네임 스페이스에서 사전을 찾을 때와 같이 직접 찾을 때와 같습니다. 이 기능을 수행 할 수 있다고 확신합니다. 변수 / 객체 / wypci가있는 네임 스페이스를 기억하십시오.

QED.


어쩌면 나는 이것을 지나치게 생각하고 있지만 ..

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'

import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)

pypi 솔루션을 업로드했습니다 . C #의 nameof기능 과 동등한 기능을 정의하는 모듈 입니다.

그것은 호출 된 프레임에 대한 바이트 코드 명령을 반복하여 전달 된 변수 / 속성의 이름을 얻습니다. 이름은 기능 이름 다음 .argreprLOAD나오는 지침 에서 찾을 수 있습니다.


나는 이런 종류의 마술을 강력하게하기 위해 패키지 마법썼다 . 당신은 쓸 수 있습니다:

from sorcery import dict_of

my_dict = dict_of(foo, bar)

대부분의 객체에는 __name__ 속성 이 없습니다 . (클래스, 함수 및 모듈은 더 많은 내장 유형을 가지고 있습니까?)

당신을 위해 다른 무엇을 기대 print(my_var.__name__)이외의 print("my_var")? 간단히 문자열을 직접 사용할 수 있습니까?

당신은 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"})

또는

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)

글쎄, 나는 며칠 전에 똑같은 요구 를 겪었고 객체 자체를 가리키는 변수의 이름 얻어야했습니다 .

왜 그렇게 필요 했습니까?

요컨대 나는 Maya 용 플러그인을 만들고 있었다 . 핵심 플러그인은 C ++를 사용하여 빌드되었지만 GUI는 프로세서를 많이 사용하지 않고 Python을 통해 작성됩니다. 아직 return까지 default 이외의 플러그인에서 여러 값을 얻는 방법을 모르기 MStatus때문에 파이썬에서 사전을 업데이트하려면 GUI를 구현하는 객체를 가리키는 변수의 이름을 전달해야했습니다. 플러그인에 대한 사전 자체를 포함하고를 사용하여 MayaMGlobal::executePythonCommand() 의 글로벌 범위에서 사전을 업데이트하십시오 .

내가 한 일을하는 것은 다음과 같습니다.

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

나는 그것이에서의 완벽한 솔루션 아니라는 것을 알고 globals많은 키 같은 가리키는 될 수있는 객체의 예는 :

a = foo()
b = a
b.name()
>>>b
or
>>>a

접근 방식은 스레드로부터 안전하지 않습니다. 내가 틀렸다면 나를 바로 잡으십시오.

적어도이 접근법 객체 자체 를 가리키는 전역 범위의 변수 이름가져 와서 내부적으로 사용하기 위해 인수로 플러그인에 전달 하여 내 문제를 해결 했습니다.

나는 이것을 int(기본 정수 클래스) 에서 시도했지만 문제는 이러한 기본 클래스가 무시되지 않는다는 것입니다 (잘못된 경우 사용 된 기술 용어를 수정하십시오). 다시 구현 int한 다음 수행 할 수 int = foo있지만 기본 요소 a = 3foo아닌 절대 대상은 아닙니다 . 당신이해야 할 것을 극복하기 위해 a = foo(3)얻기 위해 a.name()작업에.


파이썬 2.7 이상에서는 사전 이해력이있어 조금 더 짧아집니다. 가능하다면 나는 최고 답변 에서처럼 eval (eval is evil) 대신 getattr을 사용합니다. 자아는 당신이보고있는 맥락을 가진 어떤 대상이 될 수 있습니다. 객체 또는 locals = locals () 등일 수 있습니다.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}

나는 비슷한 문제를 겪고 있었다. @ S.Lott는 "변수 목록이 있다면 이름을"발견 "하는 요점은 무엇입니까?" 그리고 내 대답은 그것이 가능한지 여부와 어떤 이유로 변수를 유형별로 목록으로 정렬 하려는지 확인하는 것입니다. 어쨌든 내 연구 에서이 스레드를 발견했으며 솔루션은 약간 확장되어 @rlotun 솔루션을 기반으로합니다. @unutbu는 "이 아이디어에는 장점이 있지만 두 변수 이름이 같은 값 (예 : True)을 참조하면 의도하지 않은 변수 이름이 반환 될 수 있습니다." 이 연습에서는 사실이므로 각 가능성에 대해 이와 유사한 목록 이해를 사용하여 처리했습니다 isClass = [i for i in isClass if i != 'item']. 그렇지 않으면 "항목"이 각 목록에 나타납니다.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''

easydict를 사용할 수 있습니다

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

또 다른 예:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]

python3 에서이 함수는 스택에서 가장 외부 이름을 얻습니다.

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

코드의 어느 곳에서나 유용합니다. 첫 번째 일치 항목을 찾은 역 스택을 트래버스합니다.


이것은 끔찍한 아이디어 일지 모르지만 rlotun의 답변과 같은 줄에 있지만 정확한 결과를 더 자주 반환합니다.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

당신은 이것을 다음과 같이 부릅니다.

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"

목록을 가져와야합니다.

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]

>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

이런 식으로 'a'또는 'b'에 대한 varname을 얻습니다.

참고 URL : https://stackoverflow.com/questions/2553354/simpler-way-to-create-dictionary-of-separate-variables

반응형