[ここでお気に入りの言語]のプログラム内のすべての変数を列挙またはリストする[終了]
-
08-07-2019 - |
質問
先週、友人から、プログラム/関数/などのすべての変数を列挙または一覧表示する方法を尋ねられました。デバッグの目的で(基本的にすべてのスナップショットを取得して、設定されている変数を確認できるようにするか、設定されているかどうかを確認します)。少し調べてみると、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
次のように出力されます:
__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
PHPで部分的な方法を見つけました(リンクテキスト)ただし、すべての変数とそのタイプのみをリストし、内容はリストしません:
<?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 />'; } ?>
ということで、すべての変数とその内容をお気に入りの言語で一覧表示するにはどうすればいいですか?
VonCによる編集:この質問は、小さな&quot; code-challenge &quot ;.
同意しない場合は、タグとリンクを編集して削除してください。
解決
Pythonで、すべてのローカルバインディングを含む辞書を返すlocalsを使用して、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'>}
他のヒント
これは、 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
出力する
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"
ただし、変数識別子を表すために使用される型ではなく、変数が参照するオブジェクトの型を出力するつもりはありませんでしたか? IOW、 foo3
のタイプは String
ではなく Hash
(または dict
)である必要がありますか?その場合、コードは次のようになります
#!/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 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"
phpでこれを行うことができます:
$defined = get_defined_vars();
foreach($defined as $varName => $varValue){
echo "$varName is of type ".gettype($varValue)." and has value $varValue <br>";
}
Luaでは、基本的なデータ構造は table であり、グローバル環境_Gもテーブルです。そのため、単純な列挙がトリックを行います。
for k,v in pairs(_G) do
print(k..' is '..type(v)..' and is equal to '..tostring(v))
end
バッシュ:
set
免責事項:私の好きな言語ではありません!
完全に再帰的なPHPのワンライナー:
print_r(get_defined_vars());
最初に、単にデバッガーを使用します;-p たとえば、Visual Studioには「ローカル」があります。および「ウォッチ」必要なすべての変数などを表示するウィンドウで、任意のレベルに完全に拡張できます。
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);
}
}
}
}
Matlab:
who
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";
}
Javaでは、問題はC#に似ていますが、より冗長なモードでのみです( 知っています ;)Javaは冗長です... すでに明確にしています;))
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");
}
}
}
}
R言語の場合
ls()
および作業メモリからすべてのオブジェクトを削除する
rm(list=ls(all=TRUE))
REBOLでは、すべての変数は object!
型の context 内に存在します。グローバルコンテキストがあり、すべての関数には独自の暗黙的なローカルコンテキストがあります。新しい object!
を作成する(または context
関数を使用する)ことで、明示的に新しいコンテキストを作成できます。これは、変数(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に変更し、の最後にinでインラインスクリプトとして実行する必要があります。 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);
}
})();
Common Lisp:
(do-all-symbols (x) (print x))
すべてのバインドされた値も表示するには:
(do-all-symbols (x) (print x) (when (boundp x) (print (symbol-value x))))
これは長いリストであり、特に有用ではありません。統合デバッガーを実際に使用します。
oo-languagesのアイデアは次のとおりです。
最初に、意味のあるコンテンツを印刷するには、JavaのtoString()などが必要です。 第二に-1つのオブジェクト階層に制限する必要があります。ルートオブジェクトのコンストラクタ(EiffelのAnyなど)で、作成時にインスタンスを何らかの種類のグローバルリストに登録します。破棄中に登録を解除します(高速な挿入/検索/削除を可能にするデータ構造を必ず使用してください)。プログラムの実行中はいつでも、このデータ構造を調べて、そこに登録されているすべてのオブジェクトを印刷できます。
その構造により、エッフェルはこの目的に非常に適している可能性があります。他の言語では、ユーザー定義ではないオブジェクト(jdkクラスなど)に問題があります。 Javaでは、オープンソースのjdkを使用して独自のオブジェクトクラスを作成できる場合があります。