You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mixin元类在初始化时修改实例?伪汇编模块开发遇阻

Hey there! Let's tackle this problem step by step—since you're working on Advent of Code 2017, those pseudo-assembly problems are always a fun challenge, and building a reusable framework is such a smart approach. Below's a practical, structured solution that covers all your requirements:

Building a Reusable Pseudo-Assembly Framework for Advent of Code 2017

1. Sandboxed exec/eval for Safe Isolated Execution

First, we need a safe execution environment to run pseudo-assembly code without risking unintended side effects. We'll create a restricted namespace that only includes the operations your pseudo-assembly needs, then wrap exec and eval to use this sandbox by default.

Sandbox Implementation

class SandboxedEnvironment:
    def __init__(self):
        # Define a minimal set of safe built-ins (customize for your pseudo-assembly needs)
        self.safe_builtins = {
            'int': int,
            'float': float,
            '+': lambda a, b: a + b,
            '-': lambda a, b: a - b,
            '*': lambda a, b: a * b,
            '//': lambda a, b: a // b,
            '%': lambda a, b: a % b,
            '==': lambda a, b: a == b,
            '!=': lambda a, b: a != b,
            '<': lambda a, b: a < b,
            '>': lambda a, b: a > b,
        }
        # Local namespace to store pseudo-assembly variables (registers, memory, etc.)
        self.local_namespace = {}

    def safe_exec(self, code: str):
        """Execute code in the isolated sandbox environment."""
        exec(code, {'__builtins__': self.safe_builtins}, self.local_namespace)

    def safe_eval(self, expr: str) -> any:
        """Evaluate an expression in the sandbox and return the result."""
        return eval(expr, {'__builtins__': self.safe_builtins}, self.local_namespace)

Why This Works

  • The safe_builtins dict locks down execution to only operations your pseudo-assembly uses (no file access, system calls, etc.).
  • The local_namespace acts as the state for your interpreter—storing registers, program counters, or memory values between instructions.

2. Variable Resolution for Interpreter Namespaces

Next, we need a way to parse and resolve variables from the sandbox's namespace, handling both named registers (like reg_a) and literal values (like 5) that are common in pseudo-assembly.

Variable Resolution Method

Add this to the SandboxedEnvironment class:

def resolve_variable(self, var_ref: str) -> any:
    """Resolve a variable reference (register name or literal) from the sandbox."""
    # Check if it's a named variable in the namespace
    if var_ref in self.local_namespace:
        return self.local_namespace[var_ref]
    # Try to parse as a numeric literal
    try:
        return int(var_ref)
    except ValueError:
        try:
            return float(var_ref)
        except ValueError:
            raise NameError(f"Undefined variable or invalid literal: {var_ref}")

Customization Tip

If your pseudo-assembly uses memory addresses (like [0x10]), extend this method to parse the address and fetch values from a memory dictionary stored in local_namespace.

3. Using Mixins (or Metaclasses) to Modify Instances on Initialization

Let's clarify: Mixins are simpler for modifying instance behavior at initialization, while metaclasses are for class-level changes. Here's how to use both, depending on your needs:

Option 1: Mixin Class (Simpler for Instance Setup)

If you just want to add default state (like registers) to every interpreter instance, a mixin is the way to go—it's clean and avoids overcomplicating with metaclasses.

class InterpreterInitMixin:
    def __init__(self, *args, **kwargs):
        # Run the parent class's initialization first
        super().__init__(*args, **kwargs)
        # Add default pseudo-assembly state to the sandbox
        self.local_namespace.update({
            'reg_a': 0,
            'reg_b': 0,
            'pc': 0,  # Program counter for instruction flow
            'memory': {},  # Optional: for memory-based pseudo-assembly
        })

# Combine the mixin with our sandbox to create a ready-to-use interpreter
class PseudoAssemblyInterpreter(InterpreterInitMixin, SandboxedEnvironment):
    def __init__(self):
        super().__init__()

Option 2: Metaclass (For Class-Level Enforcement)

If you need to enforce initialization logic across multiple interpreter subclasses, a metaclass can modify the __init__ method dynamically when the class is created.

class InterpreterMeta(type):
    def __new__(cls, name, bases, attrs):
        # Capture the original __init__ if it exists
        original_init = attrs.get('__init__')

        def modified_init(self, *args, **kwargs):
            # Run the original init first
            if original_init:
                original_init(self, *args, **kwargs)
            # Inject default state
            self.local_namespace.update({
                'reg_a': 0,
                'reg_b': 0,
                'pc': 0,
            })

        # Replace the class's __init__ with our modified version
        attrs['__init__'] = modified_init
        return super().__new__(cls, name, bases, attrs)

# Apply the metaclass to our sandbox
class PseudoAssemblyInterpreter(SandboxedEnvironment, metaclass=InterpreterMeta):
    def __init__(self):
        super().__init__()

Putting It All Together (Example Usage)

Here's how you'd use this framework to run a simple pseudo-assembly snippet:

# Create an interpreter instance
interpreter = PseudoAssemblyInterpreter()

# Convert pseudo-assembly to Python-compatible code (adjust for your problem's syntax)
pseudo_code = """
reg_a += 3
reg_b = reg_a * 2
pc += 1
"""

# Execute the code and check results
interpreter.safe_exec(pseudo_code)
print(interpreter.resolve_variable('reg_a'))  # Output: 3
print(interpreter.resolve_variable('reg_b'))  # Output: 6
print(interpreter.resolve_variable('pc'))     # Output: 1

Key Tips for Advent of Code

  • Customize the Sandbox: Add any operations your specific problem requires (bitwise shifts, logical ops, etc.) to safe_builtins.
  • Add Instruction Parsing: Extend the interpreter to parse raw pseudo-assembly strings (like inc reg_a) and convert them to code that safe_exec can run.
  • Error Handling: Wrap safe_exec in try-except blocks to catch invalid instructions or variable errors, making debugging easier.

内容的提问来源于stack exchange,提问作者Stobber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:04:05