Enumerar ou lista todas as variáveis ??em um programa de [seu idioma favorito aqui] [fechado]

StackOverflow https://stackoverflow.com/questions/430811

Pergunta

Um amigo me pediu na semana passada como enumerar ou lista de todas as variáveis ??dentro de um programa / função / etc. para fins de depuração (essencialmente obter um instantâneo de tudo para que você possa ver o que as variáveis ??são definidas como, ou se eles são definidos em tudo). Olhei em volta um pouco e encontrou um relativamente bom caminho para Python:

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

for name in dir():
    myvalue = eval(name)
    print name, "is", type(name), "and is equal to ", myvalue

qual a saída vontade algo como:

__builtins__ is <type 'str'> and is equal to  <module '__builtin__' (built-in)>
__doc__ is <type 'str'> and is equal to  None
__file__ is <type 'str'> and is equal to  ./foo.py
__name__ is <type 'str'> and is equal to  __main__
foo1 is <type 'str'> and is equal to  Hello world
foo2 is <type 'str'> and is equal to  bar
foo3 is <type 'str'> and is equal to  {'1': 'a', '2': 'b'}
foo4 is <type 'str'> and is equal to  1+1

eu tenho até agora encontrado uma maneira parcial em PHP (cortesia de texto do link ), mas apenas lista todas as variáveis ??e seus tipos, não o conteúdo:

<?php
// create a few variables
$bar = 'foo';
$foo ='bar';
// create a new array object
$arrayObj = new ArrayObject(get_defined_vars());
// loop over the array object and echo variables and values
for($iterator = $arrayObj->getIterator(); $iterator->valid(); $iterator->next())
        {
        echo $iterator->key() . ' => ' . $iterator->current() . '<br />';
        }
?>

Então eu colocá-lo para você: como você listar todas as variáveis ??e seus conteúdos em seu idioma favorito

?

Editar por VonC : proponho a esta pergunta segue o espírito de um pequeno "code-challenge ".
Se você não concordar, apenas editar e remover a tag eo link.

Foi útil?

Solução

Em python, usando moradores locais que retorna um dicionário contendo todas as ligações locais, evitando assim 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'>}

Outras dicas

Este é o que olharia como em Rubi :

#!/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

qual a saída vontade

foo1 is String and is equal to "Hello world"
foo2 is String and is equal to "bar"
foo3 is String and is equal to {"1"=>"a", "2"=>"b"}
foo4 is String and is equal to "1+1"

No entanto, não quer dizer para a saída do tipo de objeto as referências variável em vez do tipo usado para representar o identificador variável? IOW, o tipo de foo3 deve ser Hash (ou dict) em vez de String, certo? Nesse caso, o código seria

#!/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

e o resultado é

foo1 is String and is equal to "Hello world"
foo2 is String and is equal to "bar"
foo3 is Hash and is equal to {"1"=>"a", "2"=>"b"}
foo4 is String and is equal to "1+1"

No PHP, você poderia fazer isso:

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

Na Lua a estrutura de dados fundamental é a tabela e até mesmo o _G ambiente global é uma tabela. Assim, uma simples enumeração irá fazer o truque.

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

IPython:

whos

Você também poderia recomendar Spyder para seu amigo que mostra essas variáveis ??parece muito com Matlab faz e fornece uma interface gráfica de linha-por-linha de depuração.

Bash:

set

Disclaimer: Não a minha linguagem favorita

A PHP de uma linha totalmente recursiva:

print_r(get_defined_vars());

Em primeiro lugar, eu simplesmente usar um ;-p depurador Visual Studio, por exemplo, tem "moradores" e janelas "relógio" que irá mostrar todas as variáveis ??etc que você quer, totalmente expansível a qualquer nível.

Em C # você não pode realmente chegar a variáveis ??método muito facilmente (e muitos bem ser removido pelo compilador) - mas você pode acessar campos reflexão etc via:

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);
            }
        }
    }
}

Matlab:

who

Perl. Não lidar com os habitantes locais my, e não filtra algumas referências inúteis, mas tudo no âmbito do pacote pode ser visto.

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

Em java, o problema seria semelhante ao C #, apenas em um modo mais detalhado (eu sei, Sei ;) Java é detalhado ... que você fez que já claro;) )

Você pode acessar a campos de objeto através Refection, mas você não pode acessar facilmente o método de variáveis ??locais. Assim, o seguinte não é para código de análise estática, mas por tempo de execução depuração somente.

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");
            }
        }
    }
}

Na linguagem R

ls()

e remover todos os objetos da memória de trabalho

rm(list=ls(all=TRUE))

Em REBOL, todas as variáveis ??viver dentro de um contexto do tipo object!. Há um contexto global, e cada função tem seu próprio contexto local implícita. Você pode criar novos contextos explicitamente criando um novo object! (ou utilizando a função context). Isto é diferente de línguas tradicionais, porque variáveis ??(chamadas de "palavras" em REBOL) carregam uma referência ao seu contexto ao redor com eles, mesmo quando eles deixaram o "escopo" em que foram definidas.

Assim, a linha inferior é que, dado um contexto, podemos listar as variáveis ??que ele define. Usaremos href="http://www.fm.tul.cz/~ladislav/rebol/contexts.html#section-12" rel="nofollow noreferrer"> context-words? função de Ladislav Mecir.

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

Agora podemos listar todas as palavras definidas no contexto global. (Há uma muito deles.)

probe context-words? system/words

Nós também podemos escrever uma função que, em seguida, lista as variáveis ??que ele define.

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

O que nós não pode fazer em REBOL, tanto quanto eu sei, é caminhar até a árvore de contexto, embora o intérprete parece ser capaz de fazer isso muito bem quando se decide como vincular palavras a seus contextos. Eu acho que isso é porque a árvore de contexto (ou seja, o alcance) pode ter uma "forma" no momento em que uma palavra é obrigado mas outra bem diferente no momento em que é avaliada.

Rápido e solução suja JavaScript se você tiver Firebug instalado (ou outro navegador com console.log). Se você não fizer isso, você vai ter que mudar console.log para document.write, e executar em pelo como um script embutido no final do seu. Mudança MAX_DEPTH de quantos níveis de recursão você quer (cuidado!).

(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);
    }
})();

Common Lisp:

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

Para também mostrar todos os valores vinculados:

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

Esta é uma longa lista, e não particularmente útil. Eu realmente usar o depurador integrado.

Aqui está uma idéia para oo-idiomas.

Primeiro, você precisa de algo como toString () em Java para imprimir conteúdos significativos. Em segundo lugar - você tem que restringir-se a um objeto-hierarquia. No construtor do objeto-raiz (como qualquer em Eiffel), seu registrar a instância sobre a criação de algum tipo de lista global. Durante a destruição, você cancelar o registro (não se esqueça de usar uma estrutura de dados que permite rápida inserção / search / remoção). Qualquer momento durante a execução do programa, você pode caminhar por esta estrutura de dados e imprimir todos os objetos registrados lá.

Devido à sua estrutura, Eiffel pode ser muito bom para esta finalidade. Outras Línguas ter problemas com objetos que não são (por exemplo, o JDK-classes) definido pelo usuário. Em Java, pode ser possível criar sua própria classe de objeto usando algum jdk-fonte aberto.

scroll top