debugging - quitar - Enumere o liste todas las variables en un programa de
quitar breakpoint netbeans (16)
Un amigo me preguntó la semana pasada cómo enumerar o enumerar todas las variables dentro de un programa / función / etc. a los fines de la depuración (básicamente obtener una instantánea de todo para que pueda ver en qué variables se establecen, o si están configuradas en absoluto). Miré un poco y encontré una manera relativamente buena 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
que dará como resultado 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
Hasta ahora he encontrado una forma parcial en PHP (cortesía del texto del enlace ) pero solo enumera todas las variables y sus tipos, no los contenidos:
<?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 />''; } ?>
Así que te lo puse: ¿cómo enumeras todas las variables y sus contenidos en tu idioma favorito?
Editar por VonC : Propongo que esta pregunta siga el espíritu de un pequeño " code-challenge ".
Si no está de acuerdo, solo edite y elimine la etiqueta y el enlace.
¡En REBOL, todas las variables viven dentro de un contexto de tipo object!
. Hay un contexto global, y cada función tiene su propio contexto local implícito. ¡Puedes crear nuevos contextos de manera explícita creando un nuevo object!
(o usando la función de context
). Esto es diferente de los lenguajes tradicionales porque las variables (llamadas "palabras" en REBOL) llevan consigo una referencia a su contexto, incluso cuando han dejado el "alcance" en el que fueron definidas.
Entonces, la conclusión es que, dado un contexto, podemos enumerar las variables que define. Usaremos las context-words?
de context-words?
Ladislav Mecir context-words?
función.
context-words?: func [ ctx [object!] ] [ bind first ctx ctx ]
Ahora podemos enumerar todas las palabras definidas en el contexto global. (Hay muchos de ellos)
probe context-words? system/words
También podemos escribir una función que luego enumera las variables que define.
enumerable: func [a b c /local x y z] [
probe context-words? bind? ''a
]
Lo que no podemos hacer en REBOL, hasta donde yo sé, es ir por el árbol de contexto, aunque el intérprete parece ser capaz de hacer esto perfectamente bien cuando decide cómo vincular palabras a sus contextos. Creo que esto se debe a que el árbol de contexto (es decir, el alcance) puede tener una "forma" en el momento en que se vincula una palabra, y otra muy distinta en el momento en que se evalúa.
Aquí hay una idea para oo-idiomas.
Primero necesita algo como toString () en Java para imprimir contenidos significativos. En segundo lugar, debe restringirse a una jerarquía de objetos. En el constructor del objeto raíz (como Any in Eiffel), registre la instancia al crearla en algún tipo de lista global. Durante la destrucción, cancela el registro (asegúrese de usar alguna estructura de datos que permita insertar / buscar / eliminar rápidamente). En cualquier momento durante la ejecución del programa, puede recorrer esta estructura de datos e imprimir todos los objetos registrados allí.
Debido a su estructura, Eiffel podría ser muy bueno para este propósito. Otros idiomas tienen problemas con objetos que no están definidos por el usuario (por ejemplo, las clases jdk). En Java, podría ser posible crear su propia clase de objeto utilizando algún jdk de fuente abierta.
Common Lisp:
(do-all-symbols (x) (print x))
Para mostrar también todos los valores encuadernados:
(do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))
Esta es una larga lista, y no particularmente útil. Realmente usaría el depurador integrado.
En Java, el problema sería similar a C #, solo en un modo más detallado (sé, lo sé;) Java es detallado ... ya lo dejaste claro;) )
Puede acceder a los campos de objetos a través de Refection, pero no puede acceder fácilmente al método de variables locales. Por lo tanto, lo siguiente no es para el código de análisis estático, sino solo para la depuración en tiempo de ejecución.
package test;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
*
* @author <a href="https://.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");
}
}
}
}
En Lua la estructura de datos fundamental es la tabla e incluso el entorno global _G es una tabla. Entonces, una enumeración simple hará el truco.
for k,v in pairs(_G) do
print(k..'' is ''..type(v)..'' and is equal to ''..tostring(v))
end
En Python, usando locals que devuelve un diccionario que contiene todos los enlaces locales, evitando así 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''>}
En el lenguaje R
ls()
y para eliminar todos los objetos de la memoria de trabajo
rm(list=ls(all=TRUE))
En php puedes hacer esto:
$defined = get_defined_vars();
foreach($defined as $varName => $varValue){
echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
En primer lugar, simplemente usaría un depurador ;- Visual Studio, por ejemplo, tiene ventanas "Locales" y "Ver" que mostrarán todas las variables, etc. que desee, completamente expandibles a cualquier nivel.
En C # no se puede acceder a las variables de método muy fácilmente (y el compilador las eliminará), pero se puede acceder a campos, etc. a través de la reflexión:
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);
}
}
}
}
Esto es lo que se vería en Ruby :
#!/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
que saldrá
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"
Sin embargo, ¿no pretendía generar el tipo de objeto al que hacen referencia las variables en lugar del tipo utilizado para representar el identificador de la variable? IOW, el tipo de foo3
debería ser Hash
(o dict
) en lugar de String
, ¿verdad? En ese caso, el código sería
#!/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
y el resultado es
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"
IPython:
whos
También podría recomendar Spyder a su amigo, que muestra esas variables de forma muy parecida a como lo hace Matlab y proporciona una GUI para la depuración línea por línea.
Matlab:
who
Perl. No maneja my
locales, y no filtra algunas referencias inútiles, pero se puede ver todo en el alcance del paquete.
my %env = %{__PACKAGE__ . ''::''};
while (($a, $b) = each %env) {
print "/$$a = $$b/n";
print "/@$a = (@$b)/n";
print "%$a = (@{[%$b]})/n";
print "*$a = $b/n";
}
Solución de JavaScript rápida y sucia si tiene FireBug instalado (u otro navegador con console.log). Si no lo hace, deberá cambiar console.log por document.write y ejecutar como un script en línea al final de su. Cambie MAX_DEPTH a la cantidad de niveles de recursión que desee (¡tenga 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);
}
})();
Un único line-up PHP recursivo:
print_r(get_defined_vars());
Intento:
set
Descargo de responsabilidad: ¡No es mi idioma favorito!