← ToolBox
/ Python 格式化
🌙
🐍 Python 格式化
Python 代码格式化:基于冒号块规则规范化缩进、统一空格、折叠多余空行。
美化
压缩
校验
复制
清空
示例
缩进
2 空格
4 空格
Tab
输出结果
等待输入...
已复制
const SAMPLE = 'def fibonacci(n):\n """Generate Fibonacci sequence."""\n a, b = 0, 1\n result = []\n for i in range(n):\n result.append(a)\n a, b = b, a + b\n return result\n\nclass Calculator:\n def __init__(self):\n self.history = []\n\n def add(self, x, y):\n return x + y\n\nif __name__ == "__main__":\n calc = Calculator()\n print(calc.add(1, 2))\n print(fibonacci(10))'; const IND = () => { const v = document.getElementById('indent').value; return v === 'tab' ? '\t' : ' '.repeat(parseInt(v)); }; function stripCommentAndString(line){ let inStr = false, strCh = ''; let result = ''; for(let i = 0; i < line.length; i++){ const c = line[i]; if(inStr){ result += c; if(c === '\\'){ if(line[i+1]){ result += line[i+1]; i++; } continue; } if(c === strCh) inStr = false; } else { if(c === '#') break; if(c === '"' || c === '\''){ inStr = true; strCh = c; result += c; } else result += c; } } return result; } function formatPython(){ setErr(''); try{ const src = document.getElementById('input').value; const lines = src.split('\n'); const out = []; const stack = [0]; let prevBlank = false; let inTripleStr = false; let tripleCh = ''; for(const line of lines){ const trimmed = line.trim(); if(inTripleStr){ out.push(line); if(line.includes(tripleCh)) inTripleStr = false; continue; } const tripleMatch = line.match(/([']{3}|["]{3})/); if(tripleMatch && line.split(tripleMatch[1]).length < 3){ tripleCh = tripleMatch[1]; inTripleStr = true; out.push(line); continue; } if(trimmed === ''){ if(!prevBlank){ out.push(''); prevBlank = true; } continue; } prevBlank = false; while(stack.length > 1 && stack[stack.length - 1] > 0 && !trimmed.startsWith('else') && !trimmed.startsWith('elif') && !trimmed.startsWith('except') && !trimmed.startsWith('finally') && !trimmed.startsWith('case') && !/^\w+:/.test(trimmed) && !(stack[stack.length - 1] === 1 && /^[a-zA-Z]/.test(trimmed) && !stack._defStarted)) { if(stack._allowDedent) { stack.pop(); } else break; } stack._allowDedent = false; const currentIndent = stack[stack.length - 1]; const content = trimmed; out.push(IND().repeat(currentIndent) + content); const codeOnly = stripCommentAndString(content); const endsColon = /:\s*$/.test(codeOnly); const isDedent = /^(return|break|continue|pass|raise|yield\b|else:|elif |except|finally:)/.test(trimmed) || /^\w+:/.test(trimmed); if(endsColon){ stack.push(currentIndent + 1); stack._allowDedent = true; } } setOut(out.join('\n')); setErr('✅ 格式化成功'); }catch(e){ setErr('❌ ' + e.message); } } function minifyPython(){ setErr(''); try{ const src = document.getElementById('input').value; const lines = src.split('\n'); const out = []; let prevBlank = false; let inTripleStr = false; let tripleCh = ''; for(let i = 0; i < lines.length; i++){ let line = lines[i]; if(inTripleStr){ out.push(line); if(line.includes(tripleCh)) inTripleStr = false; continue; } const tripleMatch = line.match(/([']{3}|["]{3})/); if(tripleMatch && line.split(tripleMatch[1]).length < 3){ tripleCh = tripleMatch[1]; inTripleStr = true; out.push(line); continue; } let trimmed = line.trim(); if(trimmed === ''){ if(!prevBlank){ out.push(''); prevBlank = true; } continue; } prevBlank = false; if(trimmed.startsWith('#')){ out.push(trimmed); continue; } const prev = out[out.length - 1] || ''; const prevCode = stripCommentAndString(prev); if(prev && !prev.endsWith(':') && !prev.endsWith('\\') && !prev.endsWith('(') && !prev.endsWith('[') && !prev.endsWith('{') && !prev.endsWith(',') && !prevCode.endsWith(':') && !trimmed.startsWith('else') && !trimmed.startsWith('elif') && !trimmed.startsWith('except') && !trimmed.startsWith('finally') && !/^\w+:/.test(trimmed) && !trimmed.startsWith('#')){ out[out.length - 1] = prev + '; ' + trimmed; } else { out.push(trimmed); } } setOut(out.join('\n')); setErr('✅ 压缩成功'); }catch(e){ setErr('❌ ' + e.message); } } function doBeautify(){ formatPython(); } function doMinify(){ minifyPython(); } function doValidate(){ setErr(''); try{ const src = document.getElementById('input').value; const lines = src.split('\n'); let depth = 0; let maxDepth = 0; let inTripleStr = false; let tripleCh = ''; const issues = []; for(let i = 0; i < lines.length; i++){ const line = lines[i]; if(inTripleStr){ if(line.includes(tripleCh)) inTripleStr = false; continue; } const tripleMatch = line.match(/([']{3}|["]{3})/); if(tripleMatch && line.split(tripleMatch[1]).length < 3){ tripleCh = tripleMatch[1]; inTripleStr = true; continue; } const codeOnly = stripCommentAndString(line); if(codeOnly.includes(':') && !/def |class |if |elif |else:|for |while |try:|except|finally:|with |match |case /.test(codeOnly.trim())){ // ignore } if(/:\s*$/.test(codeOnly)){ depth++; if(depth > maxDepth) maxDepth = depth; } if(/^\s*(return|break|continue|pass|raise)/.test(line) && depth > 0) depth = Math.max(0, depth - 1); if(/^\s*(else:|elif |except|finally:)/.test(line)) depth = Math.max(0, depth); } const stats = '✅ Python 代码分析\n' + '总行数: ' + lines.length + '\n' + '最大缩进深度: ' + maxDepth + '\n' + 'def 数量: ' + (src.match(/^\s*def\s/gm) || []).length + '\n' + 'class 数量: ' + (src.match(/^\s*class\s/gm) || []).length + '\n' + 'import 数量: ' + (src.match(/^\s*(import|from)\s/gm) || []).length + '\n' + '三引号字符串未闭合: ' + (inTripleStr ? '是 ❌' : '否 ✅'); setOut(stats); if(inTripleStr) setErr('❌ 三引号字符串未闭合'); else setErr('✅ 校验通过'); }catch(e){ setErr('❌ ' + e.message); } } function getIndent(){const v=document.getElementById('indent').value;return v==='tab'?'\t':' '.repeat(parseInt(v));} function setOut(s){document.getElementById('output').textContent=s;} function setErr(s){const e=document.getElementById('err');e.textContent=s||'';e.className='err'+(s?'':' ok');} function clearAll(){document.getElementById('input').value='';setOut('等待输入...');setErr('');} function loadSample(){document.getElementById('input').value=SAMPLE;doBeautify();}