python-expert
SKILL.md
Python Expert
Overview
Expert-level Python development guidance for building and maintaining the QWARD quantum computing metrics library. Covers library design patterns, type safety, testing, packaging, and performance optimization.
QWARD Architecture Quick Reference
qward/
├── scanner.py # Scanner (Context in Strategy pattern)
├── metrics/
│ ├── base_metric.py # MetricCalculator (Strategy Interface)
│ ├── types.py # MetricsType, MetricsId enums
│ ├── qiskit_metrics.py # Concrete Strategy
│ ├── complexity_metrics.py
│ ├── circuit_performance.py
│ ├── behavioral_metrics.py
│ ├── structural_metrics.py
│ ├── element_metrics.py
│ └── quantum_specific_metrics.py
├── schemas/ # Pydantic validation
├── visualization/ # Strategy-based visualizers
└── utils/
Core Patterns Used in QWARD
Strategy Pattern (Primary)
from abc import ABC, abstractmethod
from pydantic import BaseModel
class MetricCalculator(ABC):
"""Strategy interface - all metrics implement this."""
def __init__(self, circuit):
self._circuit = circuit
@abstractmethod
def get_metrics(self) -> BaseModel:
"""Return validated Pydantic schema object."""
...
@abstractmethod
def is_ready(self) -> bool:
...
Pydantic Schema Validation
from pydantic import BaseModel, Field, field_validator
class ComplexityMetricsSchema(BaseModel):
gate_count: int = Field(ge=0, description="Total gate count")
gate_density: float = Field(ge=0.0, le=1.0)
depth: int = Field(ge=0)
def to_flat_dict(self) -> dict:
"""Convert nested schema to flat dict for DataFrame."""
return {k: v for k, v in self.model_dump().items()}
@field_validator('gate_density')
@classmethod
def validate_density(cls, v):
if not 0 <= v <= 1:
raise ValueError('gate_density must be between 0 and 1')
return v
Reference Documentation
Load these as needed based on your task:
references/design-patterns.md- Strategy, Factory, Observer, Decorator patterns with QWARD examplesreferences/type-safety.md- Type hints, Pydantic, generics, Protocol, runtime validationreferences/testing.md- pytest fixtures, parametrize, mocking, coverage, property-based testingreferences/packaging.md- pyproject.toml, dependencies, versioning, publishing, CLI entry points
Python Best Practices for QWARD
Type Hints (Always Use)
from typing import Optional, Union
from qiskit import QuantumCircuit
from pydantic import BaseModel
def analyze_circuit(
circuit: QuantumCircuit,
shots: int = 1024,
success_criteria: Optional[callable] = None,
) -> dict[str, pd.DataFrame]:
...
Abstract Base Classes
from abc import ABC, abstractmethod
from qward.metrics.types import MetricsType, MetricsId
class MetricCalculator(ABC):
@abstractmethod
def _get_metric_type(self) -> MetricsType: ...
@abstractmethod
def _get_metric_id(self) -> MetricsId: ...
@abstractmethod
def is_ready(self) -> bool: ...
@abstractmethod
def get_metrics(self) -> BaseModel: ...
Properties Over Direct Attribute Access
class Scanner:
def __init__(self, circuit: QuantumCircuit):
self._circuit = circuit
self._strategies: list[MetricCalculator] = []
@property
def circuit(self) -> QuantumCircuit:
return self._circuit
@circuit.setter
def circuit(self, value: QuantumCircuit) -> None:
self._circuit = value
Enums for Constants
from enum import Enum
class MetricsType(Enum):
PRE_RUNTIME = "pre_runtime"
POST_RUNTIME = "post_runtime"
class MetricsId(Enum):
QISKIT = "qiskit"
COMPLEXITY = "complexity"
CIRCUIT_PERFORMANCE = "circuit_performance"
Context Managers
from contextlib import contextmanager
@contextmanager
def timer(label: str):
import time
start = time.perf_counter()
yield
elapsed = time.perf_counter() - start
print(f"{label}: {elapsed:.3f}s")
# Usage
with timer("Metric calculation"):
results = scanner.calculate_metrics()
Dataclasses for Configuration
from dataclasses import dataclass, field
@dataclass
class PlotConfig:
figsize: tuple[int, int] = (10, 6)
dpi: int = 300
style: str = "default"
color_palette: list[str] = field(default_factory=lambda: ["#1f77b4", "#ff7f0e"])
save_format: str = "png"
grid: bool = True
alpha: float = 0.7
Testing Patterns
pytest Fixtures
import pytest
from qiskit import QuantumCircuit
@pytest.fixture
def bell_circuit():
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
return qc
@pytest.fixture
def ghz_circuit():
qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
return qc
def test_qiskit_metrics(bell_circuit):
from qward.metrics import QiskitMetrics
metrics = QiskitMetrics(bell_circuit)
result = metrics.get_metrics()
assert result.basic_metrics.num_qubits == 2
assert result.basic_metrics.depth > 0
Parametrized Tests
@pytest.mark.parametrize("num_qubits,expected_depth", [
(2, 2),
(3, 3),
(5, 5),
])
def test_ghz_depth(num_qubits, expected_depth):
qc = QuantumCircuit(num_qubits)
qc.h(0)
for i in range(num_qubits - 1):
qc.cx(i, i + 1)
assert qc.depth() == expected_depth
Error Handling
class QWARDError(Exception):
"""Base exception for QWARD library."""
pass
class MetricNotReadyError(QWARDError):
"""Raised when metric prerequisites are not met."""
pass
class SchemaValidationError(QWARDError):
"""Raised when metric data fails schema validation."""
pass
# Usage
def get_metrics(self) -> BaseModel:
if not self.is_ready():
raise MetricNotReadyError(
f"{self.__class__.__name__} requires a valid circuit"
)
...
Performance Tips
- Use
__slots__for classes with many instances - Cache expensive computations with
functools.lru_cache - Use generators for large data pipelines
- Profile before optimizing:
cProfile,line_profiler - NumPy vectorization over Python loops for numeric work
- Avoid repeated
transpile()calls -- cache transpiled circuits
Code Style
- Follow PEP 8, enforced by
rufforblack - Docstrings: Google style or NumPy style (be consistent)
- Max line length: 88 (black default) or 100
- Import order: stdlib, third-party, local (enforced by
isort) - Use
f-stringsover.format()or% - Prefer
pathlib.Pathoveros.path
Weekly Installs
1
Repository
xthecapx/qiskit-qwardGitHub Stars
2
First Seen
11 days ago
Security Audits
Installed on
mcpjam1
claude-code1
junie1
windsurf1
zencoder1
crush1