2017-05-02 4 views

답변

3

compile으로 AST 인스턴스를 컴파일하면 부적절한 방법이 있습니다. 코드 객체에는 두 개의 플래그가 첨부되어 있습니다.이 중 하나는 'GENERATOR'이며이를 구분하기 위해 사용할 수 있습니다. 이 CPython의 버전 또는 구현 예를 들어

에서 정말 휴대용되지 않도록 물론이 아닌 생성 기능, 특정 컴파일 플래그에 따라하십시오 spam_gen 발전기,

func = """ 
def spam_func(): 
    print("spam") 
""" 
# Create the AST instance for it 
m = ast.parse(func) 
# get the function code 
# co_consts[0] is used because `m` is 
# compiled as a module and we want the 
# function object 
fc = compile(m, '', 'exec').co_consts[0] 
# get a string of the flags and 
# check for membership 
from dis import pretty_flags 
'GENERATOR' in pretty_flags(fc.co_flags) # False 

마찬가지로 ' 얻을 D :

gen = """ 
def spam_gen(): 
    yield "spammy" 
"""  
m = ast.parse(gen) 
gc = compile(m, '', 'exec').co_consts[0] 
'GENERATOR' in pretty_flags(gc.co_flags) # True 

이는 AST를 통과, 당신이 생각해야 할 것보다 더 많은 비열한 수 있습니다 아마 더 이해할 수있는 휴대용의 또 다른 실행 가능한 옵션입니다.


당신이 대신 AST의 함수 객체가있는 경우 당신은 항상 func.__code__.co_flags를 사용하여 같은 검사 수행 할 수 있습니다 보인다보다 더 어려울 것 AST를 순회

def spam_gen(): 
    yield "spammy" 

from dis import pretty_flags 
print(pretty_flags(spam_gen.__code__.co_flags)) 
# 'OPTIMIZED, NEWLOCALS, GENERATOR, NOFREE' 
3

을 - 컴파일러가 사용 아마가는 길. 다음은 수율 노드를 찾는 것이 소리처럼 간단하지 않은 이유의 예입니다.

>>> s1 = 'def f():\n yield' 
>>> any(isinstance(node, ast.Yield) for node in ast.walk(ast.parse(s1))) 
True 
>>> dis.pretty_flags(compile(s1, '', 'exec').co_consts[0].co_flags) 
'OPTIMIZED, NEWLOCALS, GENERATOR, NOFREE' 
>>> s2 = 'def f():\n def g():\n yield' 
>>> any(isinstance(node, ast.Yield) for node in ast.walk(ast.parse(s2))) 
True 
>>> dis.pretty_flags(compile(s2, '', 'exec').co_consts[0].co_flags) 
'OPTIMIZED, NEWLOCALS, NOFREE' 

대서양 표준시 방법

아마 기능과 람다 몸을 제외 NodeVisitor를 사용하여 필요합니다.