파이썬 코드 줄이 들여 쓰기 중첩 수준을 알 수 있습니까?
이런 식으로 :
print(get_indentation_level())
print(get_indentation_level())
print(get_indentation_level())
나는 이와 같은 것을 얻고 싶다 :
1
2
3
이 방법으로 코드를 읽을 수 있습니까?
내가 원하는 것은 코드의 더 중첩 된 부분의 출력이 더 중첩 될 것입니다. 이렇게하면 코드를보다 쉽게 읽을 수 있으며 출력을보다 쉽게 읽을 수 있습니다.
물론 나는 이것을 사용하여 수동으로 이것을 구현할 수 .format()
있었지만, 내가 염두에 두었던 것은 들여 쓰기 수준 이 print(i*' ' + string)
어디에 있는 사용자 정의 인쇄 기능이었습니다 i
. 이것은 내 터미널에서 읽을 수있는 출력을 만드는 빠른 방법입니다.
번거로운 수동 서식을 피하는 더 좋은 방법이 있습니까?
공백과 탭이 아닌 중첩 수준으로 들여 쓰기를 원하면 까다로워집니다. 예를 들어 다음 코드에서
if True:
print(
get_nesting_level())
호출 get_nesting_level
라인에 선행 공백이 없다는 사실에도 불구하고 호출 은 실제로 한 레벨 깊이 중첩 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
선행 공백이 동일하다는 사실에도 불구하고 두 호출 은 서로 다른 중첩 수준에 있습니다.
다음 코드에서
if True: print(get_nesting_level())
중첩 된 0 수준입니까, 아니면 1입니까? 의 측면에서 INDENT
그리고 DEDENT
형식적인 문법 토큰, 그것은 깊은 제로 수준입니다,하지만 당신은 같은 생각하지 않을 수 있습니다.
이 작업을 수행하려면 전체 파일을 호출 시점 및 카운트 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
예, 확실히 가능합니다. 실제 사례는 다음과 같습니다.
import inspect
def get_indentation_level():
callerframerecord = inspect.stack()[1]
frame = callerframerecord[0]
info = inspect.getframeinfo(frame)
cc = info.code_context[0]
return len(cc) - len(cc.lstrip())
if 1:
print get_indentation_level()
if 1:
print get_indentation_level()
if 1:
print get_indentation_level()
sys.current_frame.f_lineno
줄 번호를 얻기 위해 사용할 수 있습니다 . 그런 다음 들여 쓰기 수준의 수를 찾으려면 들여 쓰기가없는 이전 줄을 찾은 다음 해당 줄 번호에서 현재 줄 번호를 빼면 들여 쓰기 횟수가 표시됩니다.
import sys
current_frame = sys._getframe(0)
def get_ind_num():
with open(__file__) as f:
lines = f.readlines()
current_line_no = current_frame.f_lineno
to_current = lines[:current_line_no]
previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())
return current_line_no - previous_zoro_ind
데모:
if True:
print get_ind_num()
if True:
print(get_ind_num())
if True:
print(get_ind_num())
if True: print(get_ind_num())
# Output
1
3
5
6
이전 줄을 기반으로 들여 쓰기 수준의 수를 원한다면 :
약간의 변경만으로 할 수 있습니다.
def get_ind_num():
with open(__file__) as f:
lines = f.readlines()
current_line_no = current_frame.f_lineno
to_current = lines[:current_line_no]
previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())
return sum(1 for line in lines[previous_zoro_ind-1:current_line_no] if line.strip().endswith(':'))
데모:
if True:
print get_ind_num()
if True:
print(get_ind_num())
if True:
print(get_ind_num())
if True: print(get_ind_num())
# Output
1
2
3
3
그리고 대안으로 여기에 들여 쓰기 횟수 (공백)를 얻는 함수가 있습니다.
import sys
from itertools import takewhile
current_frame = sys._getframe(0)
def get_ind_num():
with open(__file__) as f:
lines = f.readlines()
return sum(1 for _ in takewhile(str.isspace, lines[current_frame.f_lineno - 1]))
To solve the ”real” problem that lead to your question you could implement a contextmanager which keeps track of the indention level and make the with
block structure in the code correspond to the indentation levels of the output. This way the code indentation still reflects the output indentation without coupling both too much. It is still possible to refactor the code into different functions and have other indentations based on code structure not messing with the output indentation.
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
class IndentedPrinter(object):
def __init__(self, level=0, indent_with=' '):
self.level = level
self.indent_with = indent_with
def __enter__(self):
self.level += 1
return self
def __exit__(self, *_args):
self.level -= 1
def print(self, arg='', *args, **kwargs):
print(self.indent_with * self.level + str(arg), *args, **kwargs)
def main():
indented = IndentedPrinter()
indented.print(indented.level)
with indented:
indented.print(indented.level)
with indented:
indented.print('Hallo', indented.level)
with indented:
indented.print(indented.level)
indented.print('and back one level', indented.level)
if __name__ == '__main__':
main()
Output:
0
1
Hallo 2
3
and back one level 2
>>> import inspect
>>> help(inspect.indentsize)
Help on function indentsize in module inspect:
indentsize(line)
Return the indent size, in spaces, at the start of a line of text.
'Programing' 카테고리의 다른 글
AngularJS 애플리케이션에 작은 유틸리티 기능을 어떻게 추가 할 수 있습니까? (0) | 2020.06.15 |
---|---|
JUnit 혼란 : 'Extends TestCase'또는 '@Test'? (0) | 2020.06.15 |
마우스 오버 이벤트와 마우스 입력 이벤트의 차이점은 무엇입니까? (0) | 2020.06.15 |
Eclipse에서 내 프로젝트 옆에 빨간색 느낌표가 표시되는 이유는 무엇입니까? (0) | 2020.06.15 |
크롬 확장 프로그램을 테스트하는 방법? (0) | 2020.06.15 |