[여기에 선호하는 언어] 프로그램의 모든 변수를 열거하거나 나열합니다.


80

친구가 지난주에 프로그램 / 함수 등의 모든 변수를 열거하거나 나열하는 방법을 물었습니다. 디버깅 목적으로 (기본적으로 모든 변수의 스냅 샷을 가져 와서 어떤 변수가 설정되어 있는지 또는 설정되어 있는지 확인할 수 있습니다). 나는 조금 둘러 보았고 파이썬에 상대적으로 좋은 방법을 찾았습니다.

#! / usr / bin / python                                                                                                                                                                                                                           
foo1 = "Hello world"
foo2 = "바"
foo3 = { "1": "a",
        "2": "b"}
foo4 = "1 + 1"

dir ()의 이름 :
    myvalue = eval (이름)
    print name, "is", type (name), "and is equal to", myvalue

다음과 같이 출력됩니다.

__builtins__는 <type 'str'>이고 <module '__builtin __'(내장)>과 같습니다.
__doc__는 <type 'str'>이고 None과 같습니다.
__file__은 <type 'str'>이고 ./foo.py와 같습니다.
__name__은 <type 'str'>이고 __main__과 같습니다.
foo1은 <type 'str'>이고 Hello world와 같습니다.
foo2는 <type 'str'>이고 bar와 같습니다.
foo3은 <type 'str'>이고 { '1': 'a', '2': 'b'}와 같습니다.
foo4는 <type 'str'>이고 1 + 1과 같습니다.

지금까지 PHP에서 부분적인 방법을 찾았 지만 ( 링크 텍스트 제공 ) 내용이 아닌 모든 변수와 유형 만 나열합니다.

<? php
// 몇 가지 변수 생성
$ bar = 'foo';
$ foo = '바';
// 새 배열 객체 생성
$ arrayObj = new ArrayObject (get_defined_vars ());
// 배열 객체와 에코 변수 및 값을 반복합니다.
for ($ iterator = $ arrayObj-> getIterator (); $ iterator-> valid (); $ iterator-> next ())
        {
        echo $ iterator-> key (). '=>'. $ iterator-> current (). '<br />';
        }
?>

그래서 나는 그것을 당신에게 넣습니다 : 당신이 좋아하는 언어로 모든 변수와 그 내용을 어떻게 나열합니까?


VonC 편집 :이 질문은 약간의 " 코드 도전 " 정신을 따른 다고 제안합니다 .
동의하지 않으면 태그와 링크를 편집하고 제거하십시오.


4
파이썬에서는 위에서 보여준 dir / eval 대신 locals / globals를 사용합니다. 아래를 참조하십시오.
Aaron Maenpaa

PHP에서는 훨씬 쉽게 할 수 있습니다.
Pim Jager

1
나는 동의하지 않는다. 나의 계획은 전반적으로 가장 우아한 솔루션을 선택하고 그것을 답과 presto로 설정하는 것이다. "적절한"질문으로 더 잘 분류되는 각 개별 질문에 대해 이러한 질문 중 하나를 요청했다면 다양한 언어에서 사용되는 방법이 다른 언어와 겹치는 경우가 많다는 점에 주목할 가치가 있습니다 (예 : 디버거 등 사용).
Kurt

1
좋은 게시물. 모듈에서 정의한 변수 목록을 얻으려면 이것이 필요했습니다. 'not name.startswith ('__ ')'(python 사용) 추가 테스트를 통해 이것은 나를 위해 놀라운 일입니다. 고마워요
암흑

2
한숨. 1) 여러 언어로되어 있기 때문에 너무 광범위하여 닫혀서는 안되며 2) 단일 언어의 질문에 대한 "중복 리디렉션"이어야합니다.
Charles Merriam

답변:


93

파이썬에서는 모든 로컬 바인딩을 포함하는 사전을 반환하는 로컬을 사용하여 eval을 피합니다.

>>> foo1 = "Hello world"
>>> foo2 = "bar"
>>> foo3 = {"1":"a",
...         "2":"b"}
>>> foo4 = "1+1"

>>> import pprint
>>> pprint.pprint(locals())
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 'foo1': 'Hello world',
 'foo2': 'bar',
 'foo3': {'1': 'a', '2': 'b'},
 'foo4': '1+1',
 'pprint': <module 'pprint' from '/usr/lib/python2.5/pprint.pyc'>}

11

루비 에서는 다음과 같습니다 .

#!/usr/bin/env ruby

foo1 = 'Hello world'
foo2 = 'bar'
foo3 = { '1' => 'a', '2' => 'b' }
foo4 = '1+1'

b = binding
local_variables.each do |var|
  puts "#{var} is #{var.class} and is equal to #{b.local_variable_get(var).inspect}"
end

출력됩니다

foo1은 문자열이고 "Hello world"와 같습니다.
foo2는 문자열이고 "bar"와 같습니다.
foo3은 문자열이고 { "1"=> ​​"a", "2"=> "b"}와 같습니다.
foo4는 문자열이고 "1 + 1"과 같습니다.

그러나 변수 식별자를 나타내는 데 사용되는 유형 대신 변수가 참조하는 객체 유형을 출력하려는 ​​것이 아니 었습니까? IOW, 유형은 대신 (또는 ) foo3이어야합니다 . 이 경우 코드는HashdictString

#!/usr/bin/env ruby

foo1 = 'Hello world'
foo2 = 'bar'
foo3 = { '1' => 'a', '2' => 'b' }
foo4 = '1+1'

b = binding
local_variables.each do |var|
  val = b.local_variable_get(var)
  puts "#{var} is #{val.class} and is equal to #{val.inspect}"
end

결과는

foo1은 문자열이고 "Hello world"와 같습니다.
foo2는 문자열이고 "bar"와 같습니다.
foo3은 해시이고 { "1"=> ​​"a", "2"=> "b"}와 같습니다.
foo4는 문자열이고 "1 + 1"과 같습니다.

1
또한 다음을 포함해야합니다. instance_variables global_variables class_variables 상수
Rado

루비 2.2 적어도 나는 예를 들어, 사용했다instance_variable_get(instance_variables[0])
jberryman

10

IPython :

whos

또한 Matlab과 매우 유사한 변수를 보여주고 라인 별 디버깅을위한 GUI를 제공하는 Spyder 를 친구에게 추천 할 수 있습니다 .


9

PHP에서는 다음과 같이 할 수 있습니다.

$defined = get_defined_vars(); 
foreach($defined as $varName => $varValue){
 echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}

3
+1 좋아요,이 함수는 다소 모호하지만 여기에서 가장 작은 예제 중 하나이며 일부는 여전히 PHP가 안 좋다고 말합니다. =)
Alix Axel

9

Lua에서 기본 데이터 구조는 테이블 이며 글로벌 환경 _G도 테이블입니다. 따라서 간단한 열거가 트릭을 수행합니다.

for k,v in pairs(_G) do
  print(k..' is '..type(v)..' and is equal to '..tostring(v))
end


6

완전히 재귀적인 PHP 한 줄 :

print_r(get_defined_vars());

4

먼저 디버거를 사용합니다. 예를 들어 Visual Studio에는 원하는 모든 변수 등을 표시하는 "Locals"및 "Watch"창이 있으며 모든 수준으로 완전히 확장 할 수 있습니다.

C #에서는 메서드 변수를 매우 쉽게 얻을 수 없지만 (컴파일러에 의해 제거되는 경우가 많음) 리플렉션을 통해 필드 등에 액세스 할 수 있습니다.

static class Program { // formatted for minimal vertical space
    static object foo1 = "Hello world", foo2 = "bar",
                  foo3 = new[] { 1, 2, 3 }, foo4;
    static void Main() {
        foreach (var field in typeof(Program).GetFields(
                BindingFlags.Static | BindingFlags.NonPublic)) {
            var val = field.GetValue(null);
            if (val == null) {
                Console.WriteLine("{0} is null", field.Name);
            } else {
                Console.WriteLine("{0} ({1}) = {2}",
                    field.Name, val.GetType().Name, val);
            }
        }
    }
}

4

Perl. my로컬을 처리 하지 않고 쓸모없는 참조를 필터링하지 않지만 패키지 범위의 모든 것을 볼 수 있습니다.

my %env = %{__PACKAGE__ . '::'};
while (($a, $b) = each %env) {
    print "\$$a = $$b\n";
    print "\@$a = (@$b)\n";
    print "%$a = (@{[%$b]})\n";
    print "*$a = $b\n";
}



2

자바에서 문제는 C #과 비슷할 것입니다. 더 자세한 모드에서만 (I know, I KNOW ;) Java is verbose ... you make it already clear;) )

Refection을 통해 개체 필드에 액세스 할 수 있지만 메서드 로컬 변수에 쉽게 액세스 할 수 없습니다. 따라서 다음은 정적 분석 코드가 아니라 런타임 디버깅 전용입니다.

package test;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * 
 * @author <a href="https://stackoverflow.com/users/6309/vonc">VonC</a>
 */
public class DisplayVars
{

    private static int field1 = 1;
    private static String field2 = "~2~";
    private boolean isField = false;

    /**
     * @param args
     */
    public static void main(final String[] args)
    {
        final Field[] someFields = DisplayVars.class.getDeclaredFields();
        try
        {
            displayFields(someFields);
        } catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
    }

    /**
     * @param someFields
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    @SuppressWarnings("unchecked")
    public static void displayFields(final Field[] someFields)
            throws IllegalAccessException
    {
        DisplayVars anObject = new DisplayVars();
        Object res = null;
        for (int ifields = 0; ifields < someFields.length; ifields++)
        {
            final Field aField = someFields[ifields];
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run()
                {
                    aField.setAccessible(true);
                    return null; // nothing to return
                }
            });
            res = aField.get(anObject);
            if (res != null)
            {
                System.out.println(aField.getName() + ": " + res.toString());
            } else
            {
                System.out.println(aField.getName() + ": null");
            }
        }
    }
}

또는 Apache Commons Beanutils를 사용할 수 있습니다.
Aaron Digulla

장황한 것은 Java가 아니라 코드입니다. 무의미한 주석, 시작하려면 완전히 쓸모없는 작업, 예를 들어 AccessController독립 실행 형 응용 프로그램 에서는 전체 처리 가 필요하지 않습니다 ( setAccessible어쨌든 자신의 필드에 액세스하는 데는 필요하지 않음) 또는 if처리 할 수있는 두 경우를 구별하기 위한 진술 오래된 제거 같은 방법 toString(): 전화를 System.out.println(aField.getName() + ": " + res);작품에 관계없이 여부 res입니다 null여부. 그리고 다양한 방법을 통해 코드를 확산 할 필요가 ... 어느 쪽이 없습니다
홀거

1

REBOL에서 모든 변수 는 유형 의 컨텍스트 내에 object!있습니다. 전역 컨텍스트가 있으며 모든 함수에는 자체 암시 적 로컬 컨텍스트가 있습니다. 새 컨텍스트를 만들 object!거나 context함수를 사용하여 명시 적으로 새 컨텍스트를 만들 수 있습니다 . 이것은 변수 (REBOL에서 "단어"라고 함)가 정의 된 "범위"를 벗어난 경우에도 변수 (REBOL에서 "단어"라고 함)에 대한 참조를 전달하기 때문에 기존 언어와 다릅니다.

따라서 결론은 컨텍스트가 주어지면 정의 된 변수를 나열 할 수 있다는 것입니다. Ladislav Mecir의 context-words?함수를 사용할 것 입니다.

context-words?: func [ ctx [object!] ] [ bind first ctx ctx ]

이제 전역 컨텍스트에서 정의 된 모든 단어를 나열 할 수 있습니다. ( 많이 있습니다.)

probe context-words? system/words

정의한 변수를 나열하는 함수를 작성할 수도 있습니다.

enumerable: func [a b c /local x y z] [
  probe context-words? bind? 'a
]

우리는 무엇을 할 수 REBOL에서 할, 지금까지의 내가 아는 한, 그들의 상황에 단어를 결합하는 방법을 결정할 때 인터프리터가 완벽하게이 작업을 수행 할 수있을 것으로 보인다 있지만, 상황에 맞는 나무를 거리에 있습니다. 컨텍스트 트리 (즉, 범위)는 단어가 바인딩 될 때 하나의 "모양"을 가질 수 있지만 평가할 때는 완전히 다른 모양을 가질 수 있기 때문이라고 생각합니다.


1

FireBug가 설치되어있는 경우 (또는 console.log가있는 다른 브라우저) 빠르고 더러운 JavaScript 솔루션입니다. 그렇지 않은 경우 console.log를 document.write로 변경하고. MAX_DEPTH를 원하는 재귀 수준으로 변경합니다 (조심하세요!).

(function() {
    var MAX_DEPTH = 0;
    function printObj(name, o, depth) {
        console.log(name + " type: '"+typeof o+"' value: " + o);

        if(typeof o == "function" || depth >= MAX_DEPTH) return;
        for(var c in o) {
            printObj(name+"."+c, o[c], depth+1);
        }
    }
    for(var o in window) {
        printObj(o, window[o], 0);
    }
})();

0

일반적인 Lisp :

(do-all-symbols (x) (print x))

모든 바운드 값도 표시하려면 :

(do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))

이것은 긴 목록이며 특별히 유용하지 않습니다. 정말 통합 디버거를 사용합니다.


0

다음은 oo 언어에 대한 아이디어입니다.

먼저 의미있는 내용을 인쇄하려면 Java에서 toString ()과 같은 것이 필요합니다. 둘째-자신을 하나의 개체 계층으로 제한해야합니다. 루트 개체의 생성자 (Eiffel의 Any와 같은)에서 생성시 인스턴스를 일종의 전역 목록에 등록합니다. 파기 중에 등록을 취소합니다 (빠른 삽입 / 검색 / 제거를 허용하는 일부 데이터 구조를 사용해야합니다). 프로그램 실행 중 언제든지이 데이터 구조를 살펴보고 거기에 등록 된 모든 개체를 인쇄 할 수 있습니다.

구조상 에펠은 이러한 목적에 매우 적합 할 수 있습니다. 다른 언어는 사용자가 정의하지 않은 객체 (예 : jdk-classes)에 문제가 있습니다. Java에서는 일부 오픈 소스 jdk를 사용하여 고유 한 객체 클래스를 생성 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.