programing

파이썬 코드 라인이 들여쓰기 중첩 수준을 알 수 있습니까?

magicmemo 2023. 8. 24. 21:58
반응형

파이썬 코드 라인이 들여쓰기 중첩 수준을 알 수 있습니까?

다음과 같은 것으로부터:

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공식 문법의 토큰은 깊이가 0이지만, 당신은 같은 느낌이 들지 않을 수 있습니다.


이렇게 하려면 전체 파일을 통화 시점까지 토큰화해야 합니다.INDENT그리고.DEDENT토큰모듈은 다음과 같은 기능에 매우 유용합니다.

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라인 번호를 얻기 위해.그런 다음 들여쓰기 수준의 수를 찾기 위해 들여쓰기가 0인 이전 줄을 찾은 다음 해당 줄의 번호에서 현재 줄 번호를 빼면 들여쓰기 수를 얻을 수 있습니다.

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]))

하기 위해, 할 수 , 질으로실이 "제기를하해" "결위해의" "문문고다" "제는수" "도을하" "니행있" "트습컨" "스을텍" "수하다를" "할리" "현자관" "구음" "준적추수는어" "지" "▁the다니▁which" "실" "real▁to▁and있습manager"" "▁a▁problem▁you▁implement▁that수" "▁make" "▁could" "▁keeps" "▁solve▁question▁contextwith코드의 블록 구조는 출력의 들여쓰기 수준에 해당합니다.이러한 방식으로 코드 들여쓰기는 둘 다 너무 많이 결합하지 않고 출력 들여쓰기를 반영합니다.코드를 다른 함수로 리팩터링하고 코드 구조에 기반한 다른 들여쓰기가 출력 들여쓰기를 방해하지 않도록 할 수 있습니다.

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

출력:

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.

언급URL : https://stackoverflow.com/questions/39172306/can-a-line-of-python-code-know-its-indentation-nesting-level

반응형