Quantum tapes are a datastructure that can represent quantum circuits and measurement statistics in PennyLane. They are queuing contexts that can record and process quantum operations and measurements.

In addition to being created internally by QNodes, quantum tapes can also be created, nested, expanded (via expand()), and executed manually.

Finally, quantum tapes are fully compatible with autodifferentiating via Autograd, JAX, TensorFlow, and PyTorch.


Unless you are a PennyLane or plugin developer, you likely do not need to use these classes directly.

See the quantum circuits page for more details on creating QNodes, as well as the qnode() decorator and QNode() constructor.

QuantumTape versus QuantumScript

A QuantumScript is purely a representation of a quantum circuit, and can only be constructed via initialization. Once it is initialized, the contents should then remain immutable throughout its lifetime.

>>> ops = [qml.PauliX(0)]
>>> measurements = [qml.expval(qml.PauliZ(0))]
>>> QuantumScript(ops, measurements, shots=10)
<QuantumScript: wires=[0], params=0>

A QuantumTape has additional queuing capabilities and also inherits from AnnotatedQueue. Its contents are set on exiting the context, rather than upon initialization. Since queuing requires interaction with the global singleton QueuingManager, the QuantumTape requires a threading.RLock which complicates its use in distributed situations.

>>> with QuantumTape(shots=10) as tape:
...     qml.PauliX(0)
...     qml.expval(qml.PauliZ(0))
>>> tape
<QuantumTape: wires=[0], params=0>

The QuantumTape also carries around the unprocessed queue in addition to the processed operations and measurements, to a larger memory footprint.

>>> tape.items()
((PauliX(wires=[0]), {}), (expval(PauliZ(wires=[0])), {}))

To capture a quantum function, we instead recommend queuing a quantum function into an AnnotatedQueue, and then processing that into a QuantumScript.

>>> with qml.queuing.AnnotatedQueue() as q:
...     qfunc(*args, **kwargs)
>>> QuantumScript.from_queue(q)
<QuantumScript: wires=[0], params=0>

Since queuing is also sensitive to the “identity” of an operation, not just its contents, an operation has to be copied in order for it to be used multiple times in a QuantumTape. A QuantumScript can allow the same operation to be used many times in the circuit, potentially reducing its memory footprint.

>>> op = qml.T(0)
>>> QuantumScript([op] * 100, [qml.probs(wires=0)])

Since users are familiar with the term QuantumTape, that term should be used in documentation. For performance and a reduction in unintended side effects, QuantumScript is strictly used in PennyLane source code.

pennylane.tape Package


expand_tape_state_prep(tape[, skip_first])

Expand all instances of StatePrepBase operations in the tape.

make_qscript(fn[, shots])

Returns a function that generates a qscript from a quantum function without any operation queuing taking place.


OperationRecorder([ops, measurements, …])

A template and quantum function inspector, allowing easy introspection of operators that have been applied without requiring a QNode.

QuantumScript([ops, measurements, shots, …])

The operations and measurements that represent instructions for execution on a quantum device.

QuantumTape([ops, measurements, shots, …])

A quantum tape recorder, that records and stores variational quantum programs.


An error raised with a quantum tape.

Class Inheritance Diagram

Inheritance diagram of pennylane.tape.operation_recorder.OperationRecorder, pennylane.tape.qscript.QuantumScript, pennylane.tape.tape.QuantumTape, pennylane.tape.tape.TapeError