Skip to main content

python

当进行Python代码审查、性能优化、类型安全检查或测试策略规划时,分析Python代码质量和最佳实践。

소스 정보

저장소
microwind/ai-skills
최근 소스 활동
2026년 3월 29일 10:03
감지된 SKILL.md 언어
중국어
스타
83
포크
24

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
5 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
Python分析器
description
当进行Python代码审查、性能优化、类型安全检查或测试策略规划时,分析Python代码质量和最佳实践。
license
MIT
# Python分析器技能 ## 概述 Python让编写糟糕代码变得容易。分析代码质量以防止技术债务。 **核心原则**: Python让编写糟糕代码变得容易。分析代码质量以防止技术债务。 ## 何时使用 **始终:** - Python代码审查 - 性能优化 - 类型安全检查 - 测试策略规划 - 代码重构 - 架构设计评审 **触发短语:** - "分析Python代码" - "Python性能优化" - "代码质量检查" - "Python最佳实践" - "类型安全分析" - "测试覆盖率" ## Python分析功能 ### 代码质量 - PEP 8规范检查 - 代码复杂度分析 - 代码重复检测 - 命名规范检查 - 文档字符串审查 ### 性能分析 - 瓶颈识别 - 内存使用分析 - 算法复杂度评估 - 并发性能检查 - I/O优化建议 ### 类型安全 - 类型注解检查 - 类型推断分析 - 类型错误检测 - mypy兼容性 - 运行时类型验证 ## 常见Python问题 ### 代码风格问题 ``` 问题: 不符合PEP 8编码规范 错误示例: - 变量名使用驼峰命名 - 行长度超过79字符 - 缺少空行分隔 - 导入语句不规范 解决方案: 1. 使用black自动格式化 2. 配置flake8检查 3. 使用isort整理导入 4. 遵循PEP 8指南 ``` ### 性能问题 ``` 问题: Python代码性能低下 错误示例: - 在循环中使用+拼接字符串 - 不必要的列表推导 - 全局变量访问 - 缺少缓存机制 解决方案: 1. 使用join拼接字符串 2. 优化数据结构选择 3. 使用局部变量 4. 实现缓存策略 ``` ### 类型安全问题 ``` 问题: 缺少类型注解导致运行时错误 错误示例: - 函数参数无类型提示 - 返回值类型不明确 - 可选参数未标注 - 泛型使用不当 解决方案: 1. 添加类型注解 2. 使用Optional标注可选值 3. 使用TypeVar定义泛型 4. 运行mypy检查 ``` ## 代码实现示例 ### Python代码分析器 ```python import ast import os import re from collections import defaultdict from typing import List, Dict, Any, Optional from dataclasses import dataclass from pathlib import Path @dataclass class CodeIssue: """代码问题""" file_path: str line_number: int column: int severity: str # error, warning, info message: str rule_id: str suggestion: Optional[str] = None @dataclass class FunctionMetrics: """函数指标""" name: str line_start: int line_end: int complexity: int arguments: int returns: int docstring: bool type_annotations: bool @dataclass class ClassMetrics: """类指标""" name: str line_start: int line_end: int methods: int attributes: int inheritance_depth: int docstring: bool class PythonAnalyzer: def __init__(self, config: Optional[Dict] = None): self.config = config or self.get_default_config() self.issues: List[CodeIssue] = [] self.function_metrics: List[FunctionMetrics] = [] self.class_metrics: List[ClassMetrics] = [] self.imports: Dict[str, List[str]] = defaultdict(list) self.complexity_threshold = self.config.get('complexity_threshold', 10) def get_default_config(self) -> Dict: """获取默认配置""" return { 'max_line_length': 79, 'max_function_length': 50, 'max_class_length': 200, 'complexity_threshold': 10, 'require_type_annotations': True, 'require_docstrings': True, 'check_imports': True, 'check_naming': True } def analyze_file(self, file_path: str) -> Dict[str, Any]: """分析单个Python文件""" try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() # 解析AST tree = ast.parse(content, filename=file_path) # 重置状态 self.issues = [] self.function_metrics = [] self.class_metrics = [] self.imports = defaultdict(list) # 执行各种分析 self.check_style(file_path, content) self.analyze_ast(tree, file_path) self.check_complexity(tree, file_path) self.check_type_safety(tree, file_path) self.check_documentation(tree, file_path) return { 'file_path': file_path, 'issues': self.issues, 'function_metrics': self.function_metrics, 'class_metrics': self.class_metrics, 'imports': dict(self.imports), 'summary': self.generate_summary() } except SyntaxError as e: return { 'file_path': file_path, 'error': f'语法错误: {e}', 'issues': [CodeIssue( file_path=file_path, line_number=e.lineno or 0, column=e.offset or 0, severity='error', message=f'语法错误: {e.msg}', rule_id='syntax_error' )] } except Exception as e: return { 'file_path': file_path, 'error': f'分析失败: {e}', 'issues': [] } def analyze_directory(self, directory: str) -> Dict[str, Any]: """分析整个目录""" results = [] all_issues = [] for root, dirs, files in os.walk(directory): # 跳过虚拟环境和缓存目录 dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['__pycache__', 'venv', 'env']] for file in files: if file.endswith('.py'): file_path = os.path.join(root, file) result = self.analyze_file(file_path) results.append(result) all_issues.extend(result.get('issues', [])) return { 'directory': directory, 'files': results, 'total_issues': len(all_issues), 'issue_summary': self.categorize_issues(all_issues), 'recommendations': self.generate_recommendations(all_issues) } def check_style(self, file_path: str, content: str) -> None: """检查代码风格""" lines = content.split('\n') for line_num, line in enumerate(lines, 1): # 检查行长度 if len(line) > self.config['max_line_length']: self.issues.append(CodeIssue( file_path=file_path, line_number=line_num, column=self.config['max_line_length'], severity='warning', message=f'行长度超过{self.config["max_line_length"]}字符', rule_id='line_too_long', suggestion='考虑拆分长行或使用括号换行' )) # 检查尾随空格 if line.endswith(' '): self.issues.append(CodeIssue( file_path=file_path, line_number=line_num, column=len(line.rstrip()), severity='info', message='行末有多余空格', rule_id='trailing_whitespace', suggestion='删除行末空格' )) # 检查Tab字符 if '\t' in line: self.issues.append(CodeIssue( file_path=file_path, line_number=line_num, column=line.find('\t'), severity='warning', message='使用了Tab字符,应该使用空格', rule_id='tab_character', suggestion='将Tab替换为4个空格' )) def analyze_ast(self, tree: ast.AST, file_path: str) -> None: """分析AST结构""" # 分析导入 for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: self.imports['import'].append(alias.name) elif isinstance(node, ast.ImportFrom): module = node.module or '' for alias in node.names: self.imports['from'].append(f'{module}.{alias.name}') # 分析函数和类 for node in ast.walk(tree): if isinstance(node, ast.FunctionDef): self.analyze_function(node, file_path) elif isinstance(node, ast.ClassDef): self.analyze_class(node, file_path) def analyze_function(self, node: ast.FunctionDef, file_path: str) -> None: """分析函数""" # 计算复杂度 complexity = self.calculate_complexity(node) # 统计参数 args = len(node.args.args) + len(node.args.kwonlyargs) if node.args.vararg: args += 1 if node.args.kwarg: args += 1 # 检查返回语句 returns = len([n for n in ast.walk(node) if isinstance(n, ast.Return)]) # 检查文档字符串 has_docstring = (ast.get_docstring(node) is not None) # 检查类型注解 has_type_annotations = ( all(arg.annotation for arg in node.args.args) and (node.returns is not None) ) metrics = FunctionMetrics( name=node.name, line_start=node.lineno, line_end=node.end_lineno or node.lineno, complexity=complexity, arguments=args, returns=returns, docstring=has_docstring, type_annotations=has_type_annotations ) self.function_metrics.append(metrics) # 检查问题 if complexity > self.complexity_threshold: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, column=0, severity='warning', message=f'函数{node.name}复杂度过高({complexity})', rule_id='high_complexity', suggestion='考虑拆分函数或简化逻辑' )) if not has_docstring and self.config['require_docstrings']: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, column=0, severity='info', message=f'函数{node.name}缺少文档字符串', rule_id='missing_docstring', suggestion='添加函数文档说明' )) if not has_type_annotations and self.config['require_type_annotations']: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, column=0, severity='info', message=f'函数{node.name}缺少类型注解', rule_id='missing_type_annotations', suggestion='添加参数和返回值类型注解' )) def analyze_class(self, node: ast.ClassDef, file_path: str) -> None: """分析类""" # 统计方法和属性 methods = 0 attributes = 0 for item in node.body: if isinstance(item, ast.FunctionDef): methods += 1 elif isinstance(item, ast.Assign): for target in item.targets: if isinstance(target, ast.Name): attributes += 1 # 计算继承深度 inheritance_depth = self.calculate_inheritance_depth(node) # 检查文档字符串 has_docstring = (ast.get_docstring(node) is not None) metrics = ClassMetrics( name=node.name, line_start=node.lineno, line_end=node.end_lineno or node.lineno, methods=methods, attributes=attributes, inheritance_depth=inheritance_depth, docstring=has_docstring ) self.class_metrics.append(metrics) # 检查问题 if inheritance_depth > 3: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, column=0, severity='warning', message=f'类{node.name}继承层次过深({inheritance_depth})', rule_id='deep_inheritance', suggestion='考虑使用组合替代继承' )) if not has_docstring and self.config['require_docstrings']: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, column=0, severity='info', message=f'类{node.name}缺少文档字符串', rule_id='missing_docstring', suggestion='添加类文档说明' )) def calculate_complexity(self, node: ast.AST) -> int: """计算圈复杂度""" complexity = 1 # 基础复杂度 for child in ast.walk(node): if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor)): complexity += 1 elif isinstance(child, ast.ExceptHandler): complexity += 1 elif isinstance(child, ast.With, ast.AsyncWith): complexity += 1 elif isinstance(child, ast.BoolOp): complexity += len(child.values) - 1 return complexity def calculate_inheritance_depth(self, node: ast.ClassDef) -> int: """计算继承深度""" if not node.bases: return 0 max_depth = 0 for base in node.bases: if isinstance(base, ast.Name): # 简化实现,实际需要解析整个模块 max_depth = max(max_depth, 1) return max_depth def check_complexity(self, tree: ast.AST, file_path: str) -> None: """检查复杂度相关问题""" # 检查嵌套深度 for node in ast.walk(tree): if isinstance(node, (ast.For, ast.While, ast.If)): depth = self.calculate_nesting_depth(node) if depth > 3: self.issues.append(CodeIssue( file_path=file_path, line_number=node.lineno,
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기