Repository: PennyLaneAI/pennylane
Pull request #5116 (2024-01-29 14:22:16)

[Strings1] Improve string repr of PauliX, PauliY, PauliZ 
Improving string representation of PauliX, PauliY and PauliZ to be less verbose.
Together with adding the alias for X, Y, Z and I, this makes the string outputs copy-and-paste-able.

```
>>> qml.PauliX(0)
X(0)
>>> qml.PauliX('a')
X('a')
```

Also tackling scalar products s.t.
```
>>> 0.5 * X(0) # no unnecessary bracket
0.5 * X(0)
>>> 0.5 * (X(0) + Y(1)) # keeps necessary bracket
0.5 * (X(0) + Y(1))
```
(all examples with new opmath `qml.operation.enable_new_opmath()`)

- [x] Update PauliX, PauliY, PauliZ, Identity string repr
- [x] Update tests accordingly
- [x] update SProd to not unnecessarily use brackets
- [x] add tests accordingly
- [x] Add alias for X, Y, Z and I
- [x] add tests accordingly
- [x] fix potential issues for classical shadows
- [x] changelog
- [x] handle Identity()

[sc-52831]
[sc-54957]
[sc-43897]

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`9685bd4`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/9685bd4699cd707b543186e9eda82b959618fcda?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.69% compared to head [(`49a9c51`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.68%.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #5116      +/-   ##
==========================================
- Coverage   99.69%   99.68%   -0.01%     
==========================================
  Files         393      393              
  Lines       35864    35622     -242     
==========================================
- Hits        35753    35510     -243     
- Misses        111      112       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`85dd14f`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/85dd14f3b37bba4fbf0153e0f533ac18ba46163f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.69% compared to head [(`b5ca15a`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.68%.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #5116      +/-   ##
==========================================
- Coverage   99.69%   99.68%   -0.01%     
==========================================
  Files         394      394              
  Lines       36118    35875     -243     
==========================================
- Hits        36007    35763     -244     
- Misses        111      112       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5116?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 60c72cc32..b0779a3db 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -191,6 +191,19 @@
   and the codecov check itself would never execute.
   [(#5101)](https://github.com/PennyLaneAI/pennylane/pull/5101)
 
+* String representations of Pauli operators have been improved and there are new aliases `X, Y, Z, I` for `PauliX, PauliY, PauliZ, Identity`.
+  ```
+  >>> qml.PauliX(0)
+  X(0)
+  >>> qml.PauliX('a')
+  X('a')
+  >>> 0.5 * X(0)
+  0.5 * X(0)
+  >>> 0.5 * (X(0) + Y(1))
+  0.5 * (X(0) + Y(1))
+  ```
+  [(#5116)](https://github.com/PennyLaneAI/pennylane/pull/5116)
+
 * `qml.ctrl` called on operators with custom controlled versions will return instances
   of the custom class, and it will also flatten nested controlled operators to a single
   multi-controlled operation. For `PauliX`, `CNOT`, `Toffoli`, and `MultiControlledX`,
diff --git a/pennylane/__init__.py b/pennylane/__init__.py
index 05e64279b..8a346ac0a 100644
--- a/pennylane/__init__.py
+++ b/pennylane/__init__.py
@@ -115,6 +115,7 @@ from pennylane.ops.functions import (
     commutator,
     comm,
 )
+from pennylane.ops.identity import I
 from pennylane.optimize import *
 from pennylane.debugging import snapshots
 from pennylane.shadows import ClassicalShadow
diff --git a/pennylane/ops/cv.py b/pennylane/ops/cv.py
index ae809b20b..e2b059ef3 100644
--- a/pennylane/ops/cv.py
+++ b/pennylane/ops/cv.py
@@ -44,7 +44,7 @@ from scipy.linalg import block_diag
 from pennylane import math as qml_math
 from pennylane.operation import AnyWires, CVObservable, CVOperation
 
-from .identity import Identity  # pylint: disable=unused-import
+from .identity import Identity, I  # pylint: disable=unused-import
 from .meta import Snapshot  # pylint: disable=unused-import
 
 _two_term_shift_rule = [[0.5, 1, np.pi / 2], [-0.5, 1, -np.pi / 2]]
diff --git a/pennylane/ops/identity.py b/pennylane/ops/identity.py
index 30a342f06..31a18af1e 100644
--- a/pennylane/ops/identity.py
+++ b/pennylane/ops/identity.py
@@ -62,6 +62,15 @@ class Identity(CVObservable, Operation):
     def label(self, decimals=None, base_label=None, cache=None):
         return base_label or "I"
 
+    def __repr__(self):
+        """String representation."""
+        if len(self.wires) == 0:
+            return "I()"
+        wire = self.wires[0]
+        if isinstance(wire, str):
+            return f"I('{wire}')"
+        return f"I({wire})"
+
     @staticmethod
     def compute_eigvals(n_wires=1):  # pylint: disable=arguments-differ
         r"""Eigenvalues of the operator in the computational basis (static method).
@@ -183,6 +192,9 @@ class Identity(CVObservable, Operation):
         return [Identity(wires=self.wires)]
 
 
+I = Identity
+
+
 class GlobalPhase(Operation):
     r"""A global phase operation that multiplies all components of the state by :math:`e^{-i \phi}`.
 
diff --git a/pennylane/ops/op_math/sprod.py b/pennylane/ops/op_math/sprod.py
index e00d0c137..08b4f7a19 100644
--- a/pennylane/ops/op_math/sprod.py
+++ b/pennylane/ops/op_math/sprod.py
@@ -159,7 +159,9 @@ class SProd(ScalarSymbolicOp):
 
     def __repr__(self):
         """Constructor-call-like representation."""
-        return f"{self.scalar}*({self.base})"
+        if isinstance(self.base, qml.ops.CompositeOp):
+            return f"{self.scalar} * ({self.base})"
+        return f"{self.scalar} * {self.base}"
 
     def label(self, decimals=None, base_label=None, cache=None):
         """The label produced for the SProd op."""
diff --git a/pennylane/ops/qubit/__init__.py b/pennylane/ops/qubit/__init__.py
index 147f41009..4f8902255 100644
--- a/pennylane/ops/qubit/__init__.py
+++ b/pennylane/ops/qubit/__init__.py
@@ -47,8 +47,11 @@ __ops__ = {
     "Snapshot",
     "Hadamard",
     "PauliX",
+    "X",
     "PauliY",
+    "Y",
     "PauliZ",
+    "Z",
     "PauliRot",
     "MultiRZ",
     "S",
@@ -109,8 +112,11 @@ __ops__ = {
 __obs__ = {
     "Hadamard",
     "PauliX",
+    "X",
     "PauliY",
+    "Y",
     "PauliZ",
+    "Z",
     "Hermitian",
     "Projector",
     "SparseHamiltonian",
diff --git a/pennylane/ops/qubit/non_parametric_ops.py b/pennylane/ops/qubit/non_parametric_ops.py
index 6d94e5f20..cb0ec6d24 100644
--- a/pennylane/ops/qubit/non_parametric_ops.py
+++ b/pennylane/ops/qubit/non_parametric_ops.py
@@ -210,6 +210,13 @@ class PauliX(Observable, Operation):
     def label(self, decimals=None, base_label=None, cache=None):
         return base_label or "X"
 
+    def __repr__(self):
+        """String representation."""
+        wire = self.wires[0]
+        if isinstance(wire, str):
+            return f"X('{wire}')"
+        return f"X({wire})"
+
     @staticmethod
     @lru_cache()
     def compute_matrix():  # pylint: disable=arguments-differ
@@ -333,6 +340,9 @@ class PauliX(Observable, Operation):
         return [np.pi / 2, np.pi, -np.pi / 2]
 
 
+X = PauliX
+
+
 class PauliY(Observable, Operation):
     r"""PauliY(wires)
     The Pauli Y operator
@@ -364,6 +374,13 @@ class PauliY(Observable, Operation):
         super().__init__(*params, wires=wires, id=id)
         self._pauli_rep = qml.pauli.PauliSentence({qml.pauli.PauliWord({self.wires[0]: "Y"}): 1.0})
 
+    def __repr__(self):
+        """String representation."""
+        wire = self.wires[0]
+        if isinstance(wire, str):
+            return f"Y('{wire}')"
+        return f"Y({wire})"
+
     def label(self, decimals=None, base_label=None, cache=None):
         return base_label or "Y"
 
@@ -489,6 +506,9 @@ class PauliY(Observable, Operation):
         return [0.0, np.pi, 0.0]
 
 
+Y = PauliY
+
+
 class PauliZ(Observable, Operation):
     r"""PauliZ(wires)
     The Pauli Z operator
@@ -518,6 +538,13 @@ class PauliZ(Observable, Operation):
         super().__init__(*params, wires=wires, id=id)
         self._pauli_rep = qml.pauli.PauliSentence({qml.pauli.PauliWord({self.wires[0]: "Z"}): 1.0})
 
+    def __repr__(self):
+        """String representation."""
+        wire = self.wires[0]
+        if isinstance(wire, str):
+            return f"Z('{wire}')"
+        return f"Z({wire})"
+
     def label(self, decimals=None, base_label=None, cache=None):
         return base_label or "Z"
 
@@ -645,6 +672,9 @@ class PauliZ(Observable, Operation):
         return [np.pi, 0.0, 0.0]
 
 
+Z = PauliZ
+
+
 class S(Operation):
     r"""S(wires)
     The single-qubit phase gate


Test patch:
diff --git a/pennylane/devices/tests/test_gates.py b/pennylane/devices/tests/test_gates.py
index 0a1c1303f..134732bea 100644
--- a/pennylane/devices/tests/test_gates.py
+++ b/pennylane/devices/tests/test_gates.py
@@ -58,6 +58,9 @@ ops = {
     "PauliX": qml.PauliX(wires=[0]),
     "PauliY": qml.PauliY(wires=[0]),
     "PauliZ": qml.PauliZ(wires=[0]),
+    "X": qml.X(wires=[0]),
+    "Y": qml.Y(wires=[0]),
+    "Z": qml.Z(wires=[0]),
     "PhaseShift": qml.PhaseShift(0, wires=[0]),
     "PCPhase": qml.PCPhase(0, 1, wires=[0, 1]),
     "ControlledPhaseShift": qml.ControlledPhaseShift(0, wires=[0, 1]),
@@ -274,6 +277,9 @@ single_qubit = [
     (qml.PauliX, X),
     (qml.PauliY, Y),
     (qml.PauliZ, Z),
+    (qml.X, X),
+    (qml.Y, Y),
+    (qml.Z, Z),
     (qml.Hadamard, H),
     (qml.S, S),
     (qml.T, T),
diff --git a/pennylane/devices/tests/test_measurements.py b/pennylane/devices/tests/test_measurements.py
index 203305c0f..8e3cc3a14 100644
--- a/pennylane/devices/tests/test_measurements.py
+++ b/pennylane/devices/tests/test_measurements.py
@@ -41,6 +41,9 @@ obs = {
     "PauliX": qml.PauliX(wires=[0]),
     "PauliY": qml.PauliY(wires=[0]),
     "PauliZ": qml.PauliZ(wires=[0]),
+    "X": qml.X(wires=[0]),
+    "Y": qml.Y(wires=[0]),
+    "Z": qml.Z(wires=[0]),
     "Projector": [
         qml.Projector(np.array([1]), wires=[0]),
         qml.Projector(np.array([0, 1]), wires=[0]),
diff --git a/tests/measurements/test_counts.py b/tests/measurements/test_counts.py
index c1cf04c59..87c013703 100644
--- a/tests/measurements/test_counts.py
+++ b/tests/measurements/test_counts.py
@@ -84,7 +84,7 @@ class TestCounts:
         assert repr(m1) == "CountsMP(wires=[0], all_outcomes=True)"
 
         m2 = CountsMP(obs=qml.PauliX(0), all_outcomes=True)
-        assert repr(m2) == "CountsMP(PauliX(wires=[0]), all_outcomes=True)"
+        assert repr(m2) == "CountsMP(X(0), all_outcomes=True)"
 
         m3 = CountsMP(eigvals=(-1, 1), all_outcomes=False)
         assert repr(m3) == "CountsMP(eigvals=[-1  1], wires=[], all_outcomes=False)"
diff --git a/tests/measurements/test_measurements.py b/tests/measurements/test_measurements.py
index 20e3db2a9..dd47b0fad 100644
--- a/tests/measurements/test_measurements.py
+++ b/tests/measurements/test_measurements.py
@@ -375,11 +375,11 @@ class TestProperties:
     def test_repr(self):
         """Test the string representation of a MeasurementProcess."""
         m = qml.expval(op=qml.PauliZ(wires="a") @ qml.PauliZ(wires="b"))
-        expected = "expval(PauliZ(wires=['a']) @ PauliZ(wires=['b']))"
+        expected = "expval(Z('a') @ Z('b'))"
         assert str(m) == expected
 
         m = qml.probs(op=qml.PauliZ(wires="a"))
-        expected = "probs(PauliZ(wires=['a']))"
+        expected = "probs(Z('a'))"
         assert str(m) == expected
 
         m = ProbabilityMP(eigvals=(1, 0), wires=qml.wires.Wires(0))
diff --git a/tests/ops/op_math/test_composite.py b/tests/ops/op_math/test_composite.py
index 41a75fb45..05c81d842 100644
--- a/tests/ops/op_math/test_composite.py
+++ b/tests/ops/op_math/test_composite.py
@@ -36,8 +36,8 @@ ops = (
 )
 
 ops_rep = (
-    "PauliX(wires=[0]) # PauliZ(wires=[0]) # Hadamard(wires=[0])",
-    "CNOT(wires=[0, 1]) # RX(1.23, wires=[1]) # Identity(wires=[0])",
+    "X(0) # Z(0) # Hadamard(wires=[0])",
+    "CNOT(wires=[0, 1]) # RX(1.23, wires=[1]) # I(0)",
     "IsingXX(4.56, wires=[2, 3]) # Toffoli(wires=[1, 2, 3]) # Rot(0.34, 1.0, 0, wires=[0])",
 )
 
@@ -242,7 +242,7 @@ class TestMscMethods:
     def test_nested_repr(self):
         """Test nested repr values while other nested features such as equality are not ready"""
         op = ValidOp(qml.PauliX(0), ValidOp(qml.RY(1, wires=1), qml.PauliX(0)))
-        assert repr(op) == "PauliX(wires=[0]) # (RY(1, wires=[1]) # PauliX(wires=[0]))"
+        assert repr(op) == "X(0) # (RY(1, wires=[1]) # X(0))"
 
     def test_label(self):
         """Test label method."""
diff --git a/tests/ops/op_math/test_evolution.py b/tests/ops/op_math/test_evolution.py
index 0044b3ada..7bdd7656d 100644
--- a/tests/ops/op_math/test_evolution.py
+++ b/tests/ops/op_math/test_evolution.py
@@ -107,14 +107,14 @@ class TestEvolution:
         t = qml.PauliX(0) @ qml.PauliX(1)
         isingxx = Evolution(t, 0.25)
 
-        assert repr(isingxx) == "Evolution(-0.25j PauliX(wires=[0]) @ PauliX(wires=[1]))"
+        assert repr(isingxx) == "Evolution(-0.25j X(0) @ X(1))"
 
     def test_repr_deep_operator(self):
         """Test the __repr__ method when the base is any operator with arithmetic depth > 0."""
-        base = qml.S(0) @ qml.PauliX(0)
+        base = qml.S(0) @ qml.X(0)
         op = Evolution(base, 3)
 
-        assert repr(op) == "Evolution(-3j S(wires=[0]) @ PauliX(wires=[0]))"
+        assert repr(op) == "Evolution(-3j S(wires=[0]) @ X(0))"
 
     @pytest.mark.parametrize(
         "op,decimals,expected",
diff --git a/tests/ops/op_math/test_exp.py b/tests/ops/op_math/test_exp.py
index 0eb7579d1..f01179dd1 100644
--- a/tests/ops/op_math/test_exp.py
+++ b/tests/ops/op_math/test_exp.py
@@ -649,14 +649,14 @@ class TestMiscMethods:
         t = qml.PauliX(0) @ qml.PauliX(1)
         isingxx = Exp(t, 0.25j)
 
-        assert repr(isingxx) == "Exp(0.25j PauliX(wires=[0]) @ PauliX(wires=[1]))"
+        assert repr(isingxx) == "Exp(0.25j X(0) @ X(1))"
 
     def test_repr_deep_operator(self):
         """Test the __repr__ method when the base is any operator with arithmetic depth > 0."""
         base = qml.S(0) @ qml.PauliX(0)
         op = qml.ops.Exp(base, 3)  # pylint:disable=no-member
 
-        assert repr(op) == "Exp(3 S(wires=[0]) @ PauliX(wires=[0]))"
+        assert repr(op) == "Exp(3 S(wires=[0]) @ X(0))"
 
     def test_diagonalizing_gates(self):
         """Test that the diagonalizing gates are the same as the base diagonalizing gates."""
diff --git a/tests/ops/op_math/test_pow_op.py b/tests/ops/op_math/test_pow_op.py
index f47ecb7e6..aa108e6c1 100644
--- a/tests/ops/op_math/test_pow_op.py
+++ b/tests/ops/op_math/test_pow_op.py
@@ -489,7 +489,7 @@ class TestMiscMethods:
 
     def test_repr(self):
         op = Pow(qml.PauliX(0), 2.5)
-        assert repr(op) == "PauliX(wires=[0])**2.5"
+        assert repr(op) == "X(0)**2.5"
 
         base = qml.RX(1, 0) + qml.S(1)
         op = Pow(base, 2.5)
diff --git a/tests/ops/op_math/test_sprod.py b/tests/ops/op_math/test_sprod.py
index aa3ed36d5..75b383d27 100644
--- a/tests/ops/op_math/test_sprod.py
+++ b/tests/ops/op_math/test_sprod.py
@@ -85,15 +85,15 @@ ops = (
 )
 
 ops_rep = (
-    "1.0*(PauliX(wires=[0]))",
-    "0.0*(PauliZ(wires=[0]))",
-    "1j*(Hadamard(wires=[0]))",
-    "1.23*(CNOT(wires=[0, 1]))",
-    "4.56*(RX(1.23, wires=[1]))",
-    "(1+2j)*(Identity(wires=[0]))",
-    "10*(IsingXX(4.56, wires=[2, 3]))",
-    "0j*(Toffoli(wires=[1, 2, 3]))",
-    "42*(Rot(0.34, 1.0, 0, wires=[0]))",
+    "1.0 * X(0)",
+    "0.0 * Z(0)",
+    "1j * Hadamard(wires=[0])",
+    "1.23 * CNOT(wires=[0, 1])",
+    "4.56 * RX(1.23, wires=[1])",
+    "(1+2j) * I(0)",
+    "10 * IsingXX(4.56, wires=[2, 3])",
+    "0j * Toffoli(wires=[1, 2, 3])",
+    "42 * Rot(0.34, 1.0, 0, wires=[0])",
 )
 
 
@@ -195,6 +195,30 @@ class TestInitialization:
 class TestMscMethods:
     """Test miscellaneous methods of the SProd class."""
 
+    def test_string_with_single_pauli(self):
+        """Test the string representation with single pauli"""
+        res = qml.s_prod(0.5, qml.PauliX("a"))
+        true_res = "0.5 * X('a')"
+        assert repr(res) == true_res
+
+        res = qml.s_prod(0.5, qml.PauliX(0))
+        true_res = "0.5 * X(0)"
+        assert repr(res) == true_res
+
+    def test_string_with_sum_of_pauli(self):
+        """Test the string representation with single pauli"""
+        res = qml.s_prod(0.5, qml.sum(qml.PauliX("a"), qml.PauliX("b")))
+        true_res = "0.5 * (X('a') + X('b'))"
+        assert repr(res) == true_res
+
+        res = qml.s_prod(0.5, qml.sum(qml.PauliX(0), qml.PauliX(1)))
+        true_res = "0.5 * (X(0) + X(1))"
+        assert repr(res) == true_res
+
+        res = qml.s_prod(0.5, qml.sum(qml.PauliX("a"), qml.PauliX(1)))
+        true_res = "0.5 * (X('a') + X(1))"
+        assert repr(res) == true_res
+
     @pytest.mark.parametrize("op_scalar_tup, op_rep", tuple((i, j) for i, j in zip(ops, ops_rep)))
     def test_repr(self, op_scalar_tup, op_rep):
         """Test the repr dunder method."""
diff --git a/tests/ops/op_math/test_sum.py b/tests/ops/op_math/test_sum.py
index c53fd5a8f..8089e31ae 100644
--- a/tests/ops/op_math/test_sum.py
+++ b/tests/ops/op_math/test_sum.py
@@ -798,27 +798,27 @@ class TestSortWires:
     def test_sorting_operators_with_one_wire(self):
         """Test that the sorting algorithm works for operators that act on one wire."""
         op_list = [
-            qml.PauliX(3),
-            qml.PauliZ(2),
-            qml.PauliY("a"),
+            qml.X(3),
+            qml.Z(2),
+            qml.Y("a"),
             qml.RX(1, 5),
-            qml.PauliY(0),
-            qml.PauliY(1),
-            qml.PauliZ("c"),
-            qml.PauliX(5),
-            qml.PauliZ("ba"),
+            qml.Y(0),
+            qml.Y(1),
+            qml.Z("c"),
+            qml.X(5),
+            qml.Z("ba"),
         ]
         sorted_list = Sum._sort(op_list)  # pylint: disable=protected-access
         final_list = [
-            qml.PauliY(0),
-            qml.PauliY(1),
-            qml.PauliZ(2),
-            qml.PauliX(3),
-            qml.PauliX(5),
+            qml.Y(0),
+            qml.Y(1),
+            qml.Z(2),
+            qml.X(3),
             qml.RX(1, 5),
-            qml.PauliY("a"),
-            qml.PauliZ("ba"),
-            qml.PauliZ("c"),
+            qml.X(5),
+            qml.Y("a"),
+            qml.Z("ba"),
+            qml.Z("c"),
         ]
 
         for op1, op2 in zip(final_list, sorted_list):
@@ -827,33 +827,33 @@ class TestSortWires:
     def test_sorting_operators_with_multiple_wires(self):
         """Test that the sorting algorithm works for operators that act on multiple wires."""
         op_tuple = (
-            qml.PauliX(3),
-            qml.PauliX(5),
+            qml.X(3),
+            qml.X(5),
             qml.Toffoli([2, 3, 4]),
             qml.CNOT([2, 5]),
-            qml.PauliZ("ba"),
+            qml.Z("ba"),
             qml.RX(1, 5),
-            qml.PauliY(0),
+            qml.Y(0),
             qml.CRX(1, [0, 2]),
-            qml.PauliZ(3),
+            qml.Z(3),
             qml.Toffoli([1, "c", "ab"]),
             qml.CRY(1, [1, 2]),
-            qml.PauliX("d"),
+            qml.X("d"),
         )
         sorted_list = Sum._sort(op_tuple)  # pylint: disable=protected-access
         final_list = [
-            qml.PauliY(0),
+            qml.Y(0),
             qml.CRX(1, [0, 2]),
             qml.CRY(1, [1, 2]),
             qml.Toffoli([1, "c", "ab"]),
             qml.CNOT([2, 5]),
             qml.Toffoli([2, 3, 4]),
-            qml.PauliX(3),
-            qml.PauliZ(3),
-            qml.PauliX(5),
+            qml.X(3),
+            qml.Z(3),
             qml.RX(1, 5),
-            qml.PauliZ("ba"),
-            qml.PauliX("d"),
+            qml.X(5),
+            qml.Z("ba"),
+            qml.X("d"),
         ]
 
         for op1, op2 in zip(final_list, sorted_list):
@@ -862,29 +862,29 @@ class TestSortWires:
     def test_sorting_operators_with_wire_map(self):
         """Test that the sorting algorithm works using a wire map."""
         op_list = [
-            qml.PauliX("three"),
-            qml.PauliX(5),
+            qml.X("three"),
+            qml.X(5),
             qml.Toffoli([2, "three", 4]),
             qml.CNOT([2, 5]),
             qml.RX(1, 5),
-            qml.PauliY(0),
+            qml.Y(0),
             qml.CRX(1, ["test", 2]),
-            qml.PauliZ("three"),
+            qml.Z("three"),
             qml.CRY(1, ["test", 2]),
         ]
         sorted_list = Sum._sort(  # pylint: disable=protected-access
             op_list, wire_map={0: 0, "test": 1, 2: 2, "three": 3, 4: 4, 5: 5}
         )
         final_list = [
-            qml.PauliY(0),
+            qml.Y(0),
             qml.CRX(1, ["test", 2]),
             qml.CRY(1, ["test", 2]),
             qml.CNOT([2, 5]),
             qml.Toffoli([2, "three", 4]),
-            qml.PauliX("three"),
-            qml.PauliZ("three"),
-            qml.PauliX(5),
+            qml.X("three"),
+            qml.Z("three"),
             qml.RX(1, 5),
+            qml.X(5),
         ]
 
         for op1, op2 in zip(final_list, sorted_list):
diff --git a/tests/ops/qubit/test_non_parametric_ops.py b/tests/ops/qubit/test_non_parametric_ops.py
index 3fd76efbd..eca827f4b 100644
--- a/tests/ops/qubit/test_non_parametric_ops.py
+++ b/tests/ops/qubit/test_non_parametric_ops.py
@@ -67,6 +67,27 @@ NON_PARAMETRIZED_OPERATIONS = [
     (qml.CCZ, CCZ),
 ]
 
+STRING_REPR = (
+    (qml.Identity(0), "I(0)"),
+    (qml.PauliX(0), "X(0)"),
+    (qml.PauliY(0), "Y(0)"),
+    (qml.PauliZ(0), "Z(0)"),
+    (qml.Identity("a"), "I('a')"),
+    (qml.Identity(10), "I(10)"),
+    (qml.Identity(), "I()"),
+    (qml.PauliX("a"), "X('a')"),
+    (qml.PauliY("a"), "Y('a')"),
+    (qml.PauliZ("a"), "Z('a')"),
+)
+
+
+@pytest.mark.parametrize("wire", [0, "a", "a"])
+def test_alias_XYZI(wire):
+    assert qml.PauliX(wire) == qml.X(wire)
+    assert qml.PauliY(wire) == qml.Y(wire)
+    assert qml.PauliZ(wire) == qml.Z(wire)
+    assert qml.Identity(wire) == qml.Identity(wire)
+
 
 class TestOperations:
     @pytest.mark.parametrize("op_cls, _", NON_PARAMETRIZED_OPERATIONS)
@@ -85,6 +106,11 @@ class TestOperations:
         assert np.allclose(res_static, mat, atol=tol, rtol=0)
         assert np.allclose(res_dynamic, mat, atol=tol, rtol=0)
 
+    @pytest.mark.parametrize("op, str_repr", STRING_REPR)
+    def test_string_repr(self, op, str_repr):
+        """Test explicit string representations that overwrite the Operator default"""
+        assert repr(op) == str_repr
+
 
 class TestDecompositions:
     """Tests that the decomposition of non-parametrized operations is correct"""
diff --git a/tests/pulse/test_parametrized_hamiltonian.py b/tests/pulse/test_parametrized_hamiltonian.py
index 04209f412..f8a55d05d 100644
--- a/tests/pulse/test_parametrized_hamiltonian.py
+++ b/tests/pulse/test_parametrized_hamiltonian.py
@@ -127,7 +127,7 @@ class TestInitialization:
         coeffs = [2.0, f1, f2]
         ops = [qml.PauliX(0), qml.PauliY(0), qml.PauliZ(0)]
         H = ParametrizedHamiltonian(coeffs, ops)
-        expected = "(2.0*(PauliX(wires=[0])))+(f1(params_0,t)*(PauliY(wires=[0])))+(f2(params_1,t)*(PauliZ(wires=[0])))"
+        expected = "(2.0*(X(0)))+(f1(params_0,t)*(Y(0)))+(f2(params_1,t)*(Z(0)))"
 
         assert repr(H).replace("\n", "").replace(" ", "") == expected
 
@@ -147,7 +147,9 @@ class TestInitialization:
         coeffs = [2.0, f1, f2, f3(0.5)]
         observables = [qml.PauliX(0), qml.PauliY(0), qml.PauliZ(0), qml.PauliX(0)]
         H = ParametrizedHamiltonian(coeffs, observables)
-        expected = "(2.0*(PauliX(wires=[0])))+(f1(params_0,t)*(PauliY(wires=[0])))+(f2(params_1,t)*(PauliZ(wires=[0])))+(f3(params_2,t)*(PauliX(wires=[0])))"
+        expected = (
+            "(2.0*(X(0)))+(f1(params_0,t)*(Y(0)))+(f2(params_1,t)*(Z(0)))+(f3(params_2,t)*(X(0)))"
+        )
         assert repr(H).replace("\n", "").replace(" ", "") == expected
 
     def test_wire_attribute(self):
@@ -229,7 +231,7 @@ class TestCall:
         H = ParametrizedHamiltonian(coeffs, obs)
 
         assert isinstance(H([2], 4), qml.ops.Sum)
-        assert repr(H([2], t=4)) == "(2*(GellMann2(wires=[0]))) + (10*(GellMann1(wires=[0])))"
+        assert repr(H([2], t=4)) == "(2 * GellMann2(wires=[0])) + (10 * GellMann1(wires=[0]))"
         assert np.all(
             qml.matrix(H([2], 4))
             == np.array(
diff --git a/tests/tape/test_operation_recorder.py b/tests/tape/test_operation_recorder.py
index 3d8cbfbe7..b00823e07 100644
--- a/tests/tape/test_operation_recorder.py
+++ b/tests/tape/test_operation_recorder.py
@@ -26,8 +26,8 @@ class TestOperationRecorder:
         expected_output = (
             "Operations\n"
             + "==========\n"
-            + "PauliY(wires=[0])\n"
-            + "PauliY(wires=[1])\n"
+            + "Y(0)\n"
+            + "Y(1)\n"
             + "RZ(0.4, wires=[0])\n"
             + "RZ(0.4, wires=[1])\n"
             + "CNOT(wires=[0, 1])\n"
@@ -99,8 +99,8 @@ class TestOperationRecorder:
             + "\n"
             + "Observables\n"
             + "===========\n"
-            + "PauliZ(wires=[0])\n"
-            + "PauliX(wires=[1])\n"
+            + "Z(0)\n"
+            + "X(1)\n"
         )
 
         def template(x):
diff --git a/tests/templates/test_subroutines/test_select.py b/tests/templates/test_subroutines/test_select.py
index 4e58187d6..1f9b4231e 100644
--- a/tests/templates/test_subroutines/test_select.py
+++ b/tests/templates/test_subroutines/test_select.py
@@ -37,7 +37,7 @@ def test_repr():
     control = [1]
 
     op = qml.Select(ops, control)
-    assert repr(op) == "Select(ops=(PauliX(wires=[0]), PauliY(wires=[0])), control=<Wires = [1]>)"
+    assert repr(op) == "Select(ops=(X(0), Y(0)), control=<Wires = [1]>)"
 
 
 class TestSelect:
diff --git a/tests/test_operation.py b/tests/test_operation.py
index 0bd34844f..0b5476e3c 100644
--- a/tests/test_operation.py
+++ b/tests/test_operation.py
@@ -1002,7 +1002,7 @@ class TestObservableConstruction:
         """Test the string representation of an observable with and without a return type."""
 
         m = qml.expval(qml.PauliZ(wires=["a"]) @ qml.PauliZ(wires=["b"]))
-        expected = "expval(PauliZ(wires=['a']) @ PauliZ(wires=['b']))"
+        expected = "expval(Z('a') @ Z('b'))"
         assert str(m) == expected
 
         m = qml.probs(wires=["a"])
@@ -1010,15 +1010,15 @@ class TestObservableConstruction:
         assert str(m) == expected
 
         m = qml.probs(op=qml.PauliZ(wires=["a"]))
-        expected = "probs(PauliZ(wires=['a']))"
+        expected = "probs(Z('a'))"
         assert str(m) == expected
 
         m = qml.PauliZ(wires=["a"]) @ qml.PauliZ(wires=["b"])
-        expected = "PauliZ(wires=['a']) @ PauliZ(wires=['b'])"
+        expected = "Z('a') @ Z('b')"
         assert str(m) == expected
 
         m = qml.PauliZ(wires=["a"])
-        expected = "PauliZ(wires=['a'])"
+        expected = "Z('a')"
         assert str(m) == expected
 
     def test_id(self):