program tip

변수 이름을 문자열로 변환 하시겠습니까?

radiobox 2021. 1. 8. 08:05
반응형

변수 이름을 문자열로 변환 하시겠습니까?


파이썬 변수 이름을 표시된 것과 같은 문자열로 변환하고 싶습니다. 어떻게 아이디어가 있습니까?

var = {}
print ???  # Would like to see 'var'
something_else = 3
print ???  # Would print 'something_else'

이것이 필요할 수있는 사용 시나리오가 있습니다. 나는 더 나은 방법이나 동일한 기능을 달성하는 것이 없다는 것을 의미하지 않습니다.

이것은 디버그 모드 및 기타 유사한 상황에서 오류가 발생한 경우 임의의 사전 목록을 '덤프'하는 데 유용합니다.

필요한 것은 eval()기능 의 반대입니다 .

get_indentifier_name_missing_function()

식별자 이름 ( 'variable', 'dictionary'등)을 인수로 취하고 식별자 이름이 포함 된 문자열을 반환합니다.


다음과 같은 현재 상황을 고려하십시오.

random_function(argument_data)

식별자 이름 ( 'function', 'variable', 'dictionary'등) argument_datarandom_function()(다른 식별자 이름)에 전달하는 경우 실제로 식별자 (예 :) <argument_data object at 0xb1ce10>를 다른 식별자 (예 :)에 전달합니다 <function random_function at 0xafff78>.

<function random_function at 0xafff78>(<argument_data object at 0xb1ce10>)

내 이해에서 메모리 주소 만 함수에 전달됩니다.

<function at 0xafff78>(<object at 0xb1ce10>)

따라서 random_function()해당 함수가 인수의 식별자 이름을 갖도록하려면 문자열을 인수로 전달해야합니다 .

random_function('argument_data')

random_function () 내부

def random_function(first_argument):

, 이미 제공된 문자열 'argument_data'사용하여 다음을 수행합니다.

  1. '식별자 이름'으로 사용 (표시, 로그, 문자열 분할 / 연결 등)
  2. eval()실제 식별자에 대한 참조를 가져 오므로 실제 데이터에 대한 참조를 얻기 위해 함수를 공급하십시오 .

    print("Currently working on", first_argument)
    some_internal_var = eval(first_argument)
    print("here comes the data: " + str(some_internal_var))
    

안타깝게도 모든 경우에 작동하지 않습니다. 문자열을 실제 식별자로 확인할 random_function()수있는 경우에만 작동합니다 'argument_data'. 즉, argument_data식별자 이름이 random_function()의 네임 스페이스 에서 사용 가능한 경우 .

항상 그런 것은 아닙니다.

# main1.py
import some_module1

argument_data = 'my data'

some_module1.random_function('argument_data')


# some_module1.py
def random_function(first_argument):
    print("Currently working on", first_argument)
    some_internal_var = eval(first_argument)
    print("here comes the data: " + str(some_internal_var))
######

예상 결과는 다음과 같습니다.

Currently working on: argument_data
here comes the data: my data

의 네임 스페이스 argument_data에서 식별자 이름을 사용할 수 없기 때문에 random_function()대신 다음이 생성됩니다.

Currently working on argument_data
Traceback (most recent call last):
  File "~/main1.py", line 6, in <module>
    some_module1.random_function('argument_data')
  File "~/some_module1.py", line 4, in random_function
    some_internal_var = eval(first_argument)
  File "<string>", line 1, in <module>
NameError: name 'argument_data' is not defined

이제 get_indentifier_name_missing_function()위에서 설명한대로 작동 하는 a의 가상 사용을 고려하십시오 .

다음은 더미 Python 3.0 코드입니다..

# main2.py
import some_module2
some_dictionary_1       = { 'definition_1':'text_1',
                            'definition_2':'text_2',
                            'etc':'etc.' }
some_other_dictionary_2 = { 'key_3':'value_3',
                            'key_4':'value_4', 
                            'etc':'etc.' }
#
# more such stuff
#
some_other_dictionary_n = { 'random_n':'random_n',
                            'etc':'etc.' }

for each_one_of_my_dictionaries in ( some_dictionary_1,
                                     some_other_dictionary_2,
                                     ...,
                                     some_other_dictionary_n ):
    some_module2.some_function(each_one_of_my_dictionaries)


# some_module2.py
def some_function(a_dictionary_object):
    for _key, _value in a_dictionary_object.items():
        print( get_indentifier_name_missing_function(a_dictionary_object)    +
               "    " +
               str(_key) +
               "  =  " +
               str(_value) )
######

예상 결과는 다음과 같습니다.

some_dictionary_1    definition_1  =  text_1
some_dictionary_1    definition_2  =  text_2
some_dictionary_1    etc  =  etc.
some_other_dictionary_2    key_3  =  value_3
some_other_dictionary_2    key_4  =  value_4
some_other_dictionary_2    etc  =  etc.
......
......
......
some_other_dictionary_n    random_n  =  random_n
some_other_dictionary_n    etc  =  etc.

불행하게도 get_indentifier_name_missing_function()합니다 ( '원본'식별자 이름을 볼 것이다 some_dictionary_, some_other_dictionary_2, some_other_dictionary_n). a_dictionary_object식별자 이름 만 볼 수 있습니다.

따라서 실제 결과는 다음과 같습니다.

a_dictionary_object    definition_1  =  text_1
a_dictionary_object    definition_2  =  text_2
a_dictionary_object    etc  =  etc.
a_dictionary_object    key_3  =  value_3
a_dictionary_object    key_4  =  value_4
a_dictionary_object    etc  =  etc.
......
......
......
a_dictionary_object    random_n  =  random_n
a_dictionary_object    etc  =  etc.

따라서이 경우 eval()함수 의 반대 는 그다지 유용하지 않습니다.


현재 다음을 수행해야합니다.

# main2.py same as above, except:

    for each_one_of_my_dictionaries_names in ( 'some_dictionary_1',
                                               'some_other_dictionary_2',
                                               '...',
                                               'some_other_dictionary_n' ):
        some_module2.some_function( { each_one_of_my_dictionaries_names :
                                     eval(each_one_of_my_dictionaries_names) } )


    # some_module2.py
    def some_function(a_dictionary_name_object_container):
        for _dictionary_name, _dictionary_object in a_dictionary_name_object_container.items():
            for _key, _value in _dictionary_object.items():
                print( str(_dictionary_name) +
                       "    " +
                       str(_key) +
                       "  =  " +
                       str(_value) )
    ######

결론적으로:

  • Python은 메모리 주소 만 함수에 인수로 전달합니다.
  • 식별자의 이름을 나타내는 문자열은 eval()현재 네임 스페이스에서 이름 식별자를 사용할 수있는 경우에만 함수에 의해 실제 식별자로 다시 참조 될 수 있습니다 .
  • eval()함수 의 가상 역순은 식별자 이름이 호출 코드에서 직접 '보이지 않는'경우 유용하지 않습니다. 예 : 호출 된 함수 내부.
  • 현재 하나는 함수에 전달해야합니다.
    1. 식별자 이름을 나타내는 문자열
    2. 실제 식별자 (메모리 주소)

이 모두를 통과시킴으로써 달성 될 수 'string'eval('string')동시에 호출 함수. 저는 이것이 코너 케이스 솔루션을 사용하지 않고 임의의 함수, 모듈, 네임 스페이스에서이 달걀 병아리 문제를 해결하는 가장 '일반적인'방법이라고 생각합니다. 유일한 단점은 eval()보안되지 않은 코드로 쉽게 이어질 수 있는 함수 의 사용입니다 . eval()특히 필터링되지 않은 외부 입력 데이터와 같이 함수에 아무것도 제공 하지 않도록주의해야합니다 .


이건 불가능 해.

파이썬에는 실제로 "변수"와 같은 것이 없습니다. 파이썬이 실제로 가지고있는 것은 객체를 바인딩 할 수있는 "이름"입니다. 이름이있는 경우 바인딩 될 수있는 이름은 개체에 차이가 없습니다. 수십 개의 다른 이름에 묶여 있거나 없을 수도 있습니다.

이 예를 고려하십시오.

foo = 1
bar = 1
baz = 1

이제 값이 1 인 정수 객체가 있고 거꾸로 작업하여 이름을 찾으려고한다고 가정합니다. 무엇을 인쇄 하시겠습니까? 세 가지 다른 이름에는 해당 개체가 바인딩되어 있으며 모두 똑같이 유효합니다.

Python에서 이름은 객체에 액세스하는 방법이므로 이름을 직접 사용할 수있는 방법이 없습니다. 파이썬 바이트 코드를 해킹하는 영리한 방법이나 이름의 가치를 얻는 방법이있을 수 있지만, 그것은 기껏해야 팔러 트릭입니다.

print foo인쇄 하려는 것을 알고 있다면 처음부터 "foo"실행 print "foo"하는 것이 좋습니다.

편집 : 나는 이것을 더 명확하게하기 위해 문구를 약간 변경했습니다. 또한 다음은 더 나은 예입니다.

foo = 1
bar = foo
baz = foo

실제로 Python은 0 또는 1과 같은 공통 값을 갖는 정수에 대해 동일한 객체를 재사용하므로 첫 번째 예제에서는 동일한 객체를 세 이름 모두에 바인딩해야합니다. 그러나이 예제는 명확합니다. 동일한 객체가 foo, bar 및 baz에 바인딩되어 있습니다.


파이썬 프로그램이 프로그램의 일부 변수에 대한 할당 문을 인쇄하기를 원했기 때문에이 질문을 검색했습니다. 예를 들어 "foo = 3, bar = 21, baz = 432"를 인쇄 할 수 있습니다. 인쇄 함수에는 문자열 형식의 변수 이름이 필요합니다. "foo", "bar", "baz"라는 문자열로 코드를 제공 할 수 있었지만 반복되는 느낌이었습니다. 이전 답변을 읽은 후 아래 솔루션을 개발했습니다.

globals () 함수는 변수 이름 (문자열 형식)을 키로 사용하는 dict처럼 동작합니다. 각 변수의 값에 해당하는 키를 globals ()에서 검색하고 싶었습니다. globals (). items () 메서드는 튜플 목록을 반환합니다. 각 튜플에서 첫 번째 항목은 변수 이름 (문자열)이고 두 번째 항목은 변수 값입니다. 내 variablename () 함수는 해당 목록을 검색하여 이름이 문자열 형식으로 필요한 변수의 값에 해당하는 변수 이름을 찾습니다.

itertools.ifilter () 함수는 globals (). items () 목록의 각 튜플을 함수로 테스트하여 검색을 수행합니다 lambda x: var is globals()[x[0]]. 그 함수에서 x는 테스트되는 튜플입니다. x [0]은 변수 이름 (문자열)이고 x [1]은 값입니다. lambda 함수는 테스트 된 변수의 값이 variablename ()에 전달 된 변수의 값과 같은지 테스트합니다. 실제로 is람다 함수 연산자 를 사용하여 테스트 된 변수의 이름이 variablename ()에 전달 된 변수와 정확히 동일한 객체에 바인딩되었는지 여부를 테스트합니다. 그렇다면 튜플은 테스트를 통과하고 ifilter ()에 의해 반환됩니다.

itertools.ifilter () 함수는 실제로 제대로 호출 될 때까지 결과를 반환하지 않는 반복자를 반환합니다. 제대로 호출되도록하기 위해 list comprehension 안에 넣었습니다 [tpl[0] for tpl ... globals().items())]. 목록 이해는 tpl[0]변수 값을 무시하고 변수 이름 만 저장 합니다. 생성 된 목록에는 variablename ()에 전달 된 변수 값에 바인딩 된 하나 이상의 이름 (문자열)이 포함됩니다.

아래 표시된 variablename () 사용에서 원하는 문자열이 목록의 요소로 반환됩니다. 대부분의 경우 목록에서 유일한 항목입니다. 그러나 다른 변수 이름에 동일한 값이 할당되면 목록이 더 길어집니다.

>>> def variablename(var):
...     import itertools
...     return [tpl[0] for tpl in 
...     itertools.ifilter(lambda x: var is x[1], globals().items())]
... 
>>> var = {}
>>> variablename(var)
['var']
>>> something_else = 3
>>> variablename(something_else)
['something_else']
>>> yet_another = 3
>>> variablename(something_else)
['yet_another', 'something_else']

기술적으로는 정보를 사용할 수 있지만 다른 사람들이 요청했듯이 현명한 방식으로 정보를 어떻게 활용 하시겠습니까?

>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 
'x': 52, '__doc__': None, '__package__': None}

이것은 변수 이름이 globals () 사전에 문자열로 존재 함을 보여줍니다.

>>> globals().keys()[2]
'x'

이 경우 세 번째 키가되지만 주어진 변수 이름이 어디에서 끝날지 알 수있는 신뢰할 수있는 방법은 없습니다.

>>> for k in globals().keys():
...   if not k.startswith("_"):
...     print k
...
x
>>>

이와 같은 시스템 변수를 필터링 할 수 있지만 여전히 모든 항목을 얻을 수 있습니다. 위의 코드를 실행하면 dict에서 "x"의 위치를 ​​변경하는 또 다른 변수 "k"가 생성되었습니다.

그러나 이것은 당신에게 유용한 시작일 것입니다. 이 기능을 원하는 것이 무엇인지 알려 주시면 더 유용한 정보가 제공 될 수 있습니다.


두 번째 클래스가 아닌 변수 인 한 여기에서 작동합니다.

def print_var_name(variable):
 for name in globals():
     if eval(name) == variable:
        print name
foo = 123
print_var_name(foo)
>>>foo

이것은 클래스 멤버에게 발생합니다.

class xyz:
     def __init__(self):
         pass
member = xyz()
print_var_name(member)
>>>member

클래스에 대한 ans (예시) :

abc = xyz
print_var_name(abc)
>>>abc
>>>xyz

그래서 수업의 경우 이름과 속성을 제공합니다.


어떻게 든 이름을 인쇄하려는 변수를 참조해야합니다. 따라서 다음과 같이 보일 것입니다.

print varname(something_else)

그러한 기능은 없지만 만약 있다면 그것은 무의미 할 것입니다. 를 입력해야 something_else하므로 왼쪽과 오른쪽에 따옴표를 입력하여 이름을 문자열로 인쇄 할 수도 있습니다.

print "something_else"

당신은 무엇을 성취하려고합니까? 설명하는대로 수행 할 이유가 전혀 없으며 해결하려는 문제에 대해 훨씬 더 나은 해결책이있을 수 있습니다.

요청하는 것에 대한 가장 확실한 대안은 사전입니다. 예를 들면 :

>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something

대부분 a .. 도전으로 원하는 결과를 구현했습니다. 이 코드를 사용하지 마십시오!

#!/usr/bin/env python2.6
class NewLocals:
    """Please don't ever use this code.."""
    def __init__(self, initial_locals):
        self.prev_locals = list(initial_locals.keys())

    def show_new(self, new_locals):
        output = ", ".join(list(set(new_locals) - set(self.prev_locals)))
        self.prev_locals = list(new_locals.keys())
        return output
# Set up
eww = None
eww = NewLocals(locals())

# "Working" requested code

var = {}

print eww.show_new(locals())  # Outputs: var

something_else = 3
print eww.show_new(locals()) # Outputs: something_else

# Further testing

another_variable = 4
and_a_final_one = 5

print eww.show_new(locals()) # Outputs: another_variable, and_a_final_one

Django는 필드 이름을 생성 할 때 이것을하지 않습니까?

http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names

나에게 합리적인 것 같습니다.


I think this is a cool solution and I suppose the best you can get. But do you see any way to handle the ambigious results, your function may return? As "is" operator behaves unexpectedly with integers shows, low integers and strings of the same value get cached by python so that your variablename-function might priovide ambigous results with a high probability. In my case, I would like to create a decorator, that adds a new variable to a class by the varialbename i pass it:

def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency

But if your method returns ambigous results, how can I know the name of the variable I added?

var any_var="myvarcontent"
var myvar="myvarcontent"
@inject(myvar)
class myclasss():
    def myclass_method(self):
        print self.__myvar    #I can not be sure, that this variable will be set...

Maybe if I will also check the local list I could at least remove the "dependency"-Variable from the list, but this will not be a reliable result.


Here is a succinct variation that lets you specify any directory. The issue with using directories to find anything is that multiple variables can have the same value. So this code returns a list of possible variables.

def varname( var, dir=locals()):
  return [ key for key, val in dir.items() if id( val) == id( var)]

This will work for simnple data types (str, int, float, list etc.)

>>> def my_print(var_str) : 
      print var_str+':', globals()[var_str]
>>> a = 5
>>> b = ['hello', ',world!']
>>> my_print('a')
a: 5
>>> my_print('b')
b: ['hello', ',world!']

It's not very Pythonesque but I was curious and found this solution. You need to duplicate the globals dictionary since its size will change as soon as you define a new variable.

def var_to_name(var):
    # noinspection PyTypeChecker
    dict_vars = dict(globals().items())

    var_string = None

    for name in dict_vars.keys():
        if dict_vars[name] is var:
            var_string = name
            break

    return var_string


if __name__ == "__main__":
    test = 3
    print(f"test = {test}")
    print(f"variable name: {var_to_name(test)}")

which returns:

test = 3
variable name: test

print "var"
print "something_else"

Or did you mean something_else?

ReferenceURL : https://stackoverflow.com/questions/1534504/convert-variable-name-to-string

반응형