Skip to content

Instantly share code, notes, and snippets.

@gvx
Last active February 15, 2021 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvx/667efcd263b18d313801c1b1ffa41509 to your computer and use it in GitHub Desktop.
Save gvx/667efcd263b18d313801c1b1ffa41509 to your computer and use it in GitHub Desktop.
Find all occurrences of for ... else
import ast
from pathlib import Path
class Visitor(ast.NodeVisitor):
def __init__(self):
self.for_found = 0
self.for_else_found = 0
self.while_found = 0
self.while_else_found = 0
self.files_tried = 0
self.files_skipped = 0
def visit_For(self, node):
self.for_found += 1
if node.orelse:
self.for_else_found += 1
self.generic_visit(node)
def visit_While(self, node):
self.while_found += 1
if node.orelse:
self.while_else_found += 1
self.generic_visit(node)
def visit_file(file: Path, visitor: Visitor):
try:
module = ast.parse(file.read_text(encoding='utf-8'))
except Exception:
visitor.files_skipped += 1
return
visitor.files_tried += 1
visitor.visit(module)
def visit_all(directory: Path, visitor: Visitor):
for file in directory.rglob('*.py'):
visit_file(file, visitor)
if __name__ == '__main__':
visitor = Visitor()
visit_all(Path.cwd(), visitor)
print('for loops', visitor.for_found)
print('for elses', visitor.for_else_found, f'({visitor.for_else_found / visitor.for_found:.2%})')
print('while loops', visitor.while_found)
print('while elses', visitor.while_else_found, f'({visitor.while_else_found / visitor.while_found:.2%})')
print('# modules', visitor.files_tried)
print('# skipped', visitor.files_skipped)
@gvx
Copy link
Author

gvx commented May 28, 2018

Results in various codebases and collections of projects:

for loops 1815
for elses 60 (3.31%)
while loops 347
while elses 4 (1.15%)
# modules 598
# skipped 2

for loops 140
for elses 3 (2.14%)
while loops 35
while elses 0 (0.00%)
# modules 112
# skipped 3

@alexpovel
Copy link

Well written script!

While on the topic, there is also try/except/else, which could even also be used here:

def visit_file(file: Path, visitor: Visitor):
    try:
        module = ast.parse(file.read_text(encoding='utf-8'))
    except Exception:
        visitor.files_skipped += 1
    else:
        visitor.files_tried += 1
        visitor.visit(module)

I know this is an old gist, but just thought it's relevant in a funny way and wanted to share.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment