Repository: Qiskit/qiskit

Issue:
Using a numpy integer type as an index for a QuantumRegister fails
### Information

- **Qiskit Terra version**: 0.11.1
- **Python version**:  3.7.6
- **Operating system**: Ubuntu 18.04.4 LTS

### What is the current behavior?

An error is raised:

```
File "/lib/python3.7/site-packages/qiskit/circuit/register.py", line 90, in __getitem__
    raise CircuitError("expected integer or slice index into register")
qiskit.circuit.exceptions.CircuitError: 'expected integer or slice index into register'
```

### Steps to reproduce the problem

```python
from qiskit import QuantumRegister
import numpy as np
qr = QuantumRegister(3)
qubit_index = np.int64(0)
qubit = qr[qubit_index]
```

### What is the expected behavior?

Since numpy is used extensively in scientific programming, the type checking should not be as strict.

### Suggested solutions

Change line 89 of register.py from:

```python
if not isinstance(key, (int, slice, list)):
```

to

```python
if not isinstance(key, (int, slice, list, np.integer)):
```



Discussion:
@bjader I agree, please feel free to push a PR with your suggested change (probably with a unit test covering passing a numpy int in), it'll be an easy approval :)
Great, I'll get round to it over the next few days! Looking forward to my first PR
Why not use the Python `numbers` library here?
@nonhermitian In what way? Does the `numbers` library have a common type between python ints and numpy ints? I'm not familiar with the library.

Edit: Aha, as such?

```
isinstance(np.int64(0), numbers.Number)
Out[31]: True
```
Everything should be a numbers.Number
But floats and complex are also numbers.

I think the approach should be trying casting to int before the type check. My 2 cents.
`isinstance(foo, numbers.Integral) and 0 <= foo < len(self)` should cover those cases.

Agree, in general, try/catch is more pythonic (and would simplify implementation), but would leave gaps for users who are new to python. e.g. `int(3.5) == 3`.
Actually, `numbers.Integral` evaluates to False if passed a complex. So using `Integral` should be fine I think.
If another user wants to make the change / pull request please feel free. Unfortunately, I've become swamped since the pandemic.
Hi, I am keen to contribute to solving this as my first issue. Can I work on this?
Yes that would be great! Do you know where to start or do you need a hand? 🙂 
Thank you!
I changed line 120/121 of register.py from:
```
if not isinstance(key, (int, slice, list)):
```
to
```
if not isinstance(key, (int, slice, list, np.integer)):
```
as suggested above and it works:
![image](https://user-images.githubusercontent.com/43485111/85038032-b0692100-b1b8-11ea-87a2-8a769daf55ba.png)
Can I make a pull request?

Can you use `numbers.Integral` instead, as it also covers other integer types? I.e.
```
if not isinstance(key, (numbers.Integral, slice, list)):
```
Yes numbers.Integral works too
Then you can open a PR 👍 

Resolving patch:
diff --git a/qiskit/circuit/register.py b/qiskit/circuit/register.py
--- a/qiskit/circuit/register.py
+++ b/qiskit/circuit/register.py
@@ -19,6 +19,7 @@
 """
 import re
 import itertools
+import numbers
 
 from qiskit.circuit.exceptions import CircuitError
 
@@ -117,7 +118,7 @@ def __getitem__(self, key):
             CircuitError: if the `key` is not an integer.
             QiskitIndexError: if the `key` is not in the range `(0, self.size)`.
         """
-        if not isinstance(key, (int, slice, list)):
+        if not isinstance(key, (numbers.Integral, slice, list)):
             raise CircuitError("expected integer or slice index into register")
         if isinstance(key, slice):
             return self._bits[key]


Test patch:
diff --git a/test/python/circuit/test_circuit_registers.py b/test/python/circuit/test_circuit_registers.py
--- a/test/python/circuit/test_circuit_registers.py
+++ b/test/python/circuit/test_circuit_registers.py
@@ -70,6 +70,18 @@ def test_qarg_numpy_int_size(self):
         self.assertEqual(qr1.size, 10)
         self.assertEqual(type(qr1), QuantumRegister)
 
+    def test_register_int_types(self):
+        """Test attempt to pass different types of integer as indices
+        of QuantumRegister and ClassicalRegister
+        """
+        ints = [int(2), np.int(2), np.int32(2), np.int64(2)]
+        for index in ints:
+            with self.subTest(index=index):
+                qr = QuantumRegister(4)
+                cr = ClassicalRegister(4)
+                self.assertEqual(qr[index], qr[2])
+                self.assertEqual(cr[index], cr[2])
+
     def test_numpy_array_of_registers(self):
         """Test numpy array of Registers .
         See https://github.com/Qiskit/qiskit-terra/issues/1898