次のようなものです:
print(get_indentation_level())
print(get_indentation_level())
print(get_indentation_level())
次のようなものを取得したいです:
1
2
3
コードはこのようにして自分自身を読み取ることができますか?
私が望んでいるのは、コードのネストされた部分からの出力をさらにネストすることです。これによりコードが読みやすくなるのと同じように、出力も読みやすくなります。
もちろん、たとえば を使ってこれを手動で実装することもできます.format()
が、私が考えていたのは、インデント レベルがprint(i*' ' + string)
どこにあるかを示すカスタム プリント関数でしたi
。これは、端末上で読み取り可能な出力を素早く作成する方法です。
面倒な手動フォーマットを回避できる、より良い方法はありますか?
ベストアンサー1
スペースやタブではなく、ネスト レベルでインデントを行う場合、状況は複雑になります。たとえば、次のコードでは次のようになります。
if True:
print(
get_nesting_level())
get_nesting_level
呼び出しの行の先頭に空白がないにもかかわらず、呼び出しは実際には 1 レベル深くネストされていますget_nesting_level
。一方、次のコードでは:
print(1,
2,
get_nesting_level())
get_nesting_level
行の先頭に空白があるにもかかわらず、の呼び出しは0 レベルの深さにネストされています。
次のコードでは:
if True:
if True:
print(get_nesting_level())
if True:
print(get_nesting_level())
get_nesting_level
先頭の空白は同じであるにもかかわらず、 の2 つの呼び出しは異なるネスト レベルにあります。
次のコードでは:
if True: print(get_nesting_level())
INDENT
これはネストされたレベルが 0 ですか、それとも 1 ですか? 正式な文法のトークンに関してはDEDENT
、ネストされたレベルは 0 ですが、同じようには感じないかもしれません。
これを実行するには、呼び出しの時点までファイル全体をトークン化し、トークンINDENT
をカウントする必要がありますDEDENT
。tokenize
モジュールはこのような機能に非常に役立ちます:
import inspect
import tokenize
def get_nesting_level():
caller_frame = inspect.currentframe().f_back
filename, caller_lineno, _, _, _ = inspect.getframeinfo(caller_frame)
with open(filename) as f:
indentation_level = 0
for token_record in tokenize.generate_tokens(f.readline):
token_type, _, (token_lineno, _), _, _ = token_record
if token_lineno > caller_lineno:
break
elif token_type == tokenize.INDENT:
indentation_level += 1
elif token_type == tokenize.DEDENT:
indentation_level -= 1
return indentation_level