REF: move roperators to pandas.core
State: closed

This PR does 2 things:

- change `pandas.core.ops.roperator` imports to all import the module and use `roperator.<rop>` instead of importing the actual functions (this makes the usage similar as for the non-reversed operators with `import operator`)
- move `roperator.py` from pandas/core/ops to pandas/core, so it can be imported in `pandas.core.computation.expressions` without relying on the `pandas.core.ops` module, which in its turn means we can move the inline import of `pandas.core.computation.expressions` in `pandas.core.ops.array_ops` to a top-level import (better for performance for a function that is called repeatedly)

I think the first change is useful anyway (can also do it as a separate PR), for the second point, a possible alternative would be to move `pandas.core.computation.expressions` from the computation/ module to the ops/ module

One consequence of this, though: by always importing this in `array_ops`, it gets imported on `import pandas` time, and thus `numexpr` always gets imported at that point (while now it's only a delayed import when doing a first operation). 

Now, I checked with `python -X importtime -c "import numpy, pandas, numexpr"`, and after already having import numpy (and pandas), also import numexpr is only a small addition (most of the import of numexpr is import numpy). 
Based on running that a few times, it seems to adds 1.5-2 % to the total pandas import time.  

Labels:
name: Refactor
description: Internal refactoring of code
name: Numeric Operations
description: Arithmetic, Comparison, and Logical operations

Comments:
> possible alternative would be to move pandas.core.computation.expressions from the computation/ module to the ops/ module

i think this would be marginally nicer.  not a big deal.  might want to move expressions.check to eg compat.numexpr
One additional consideration is that expressions.py also contains the `where` function, which doesn't necessarily fit in `ops/` ?
(and I still need to update the imports in conftest.py)
> One additional consideration is that expressions.py also contains the where function, which doesn't necessarily fit in ops/ ?

Thats a fair point.  Either way is fine, really.  Could reasonably split expressions.py into where/evaluate pieces, but its too early in the AM to go down this rabbit hole.
Fixed the failing tests. This should be good now (assuming we leave expressions.py in /computation as is, for now)
One additional point here: by always importing this in `array_ops`, it gets imported on `import pandas` time, and thus `numexpr` always gets imported at that point (while now it's only a delayed import when doing a first operation). 

Now, I checked with `python -X importtime -c "import numpy, pandas, numexpr"`, and after already having import numpy (and pandas), also import numexpr is only a small addition (most of the import of numexpr is import numpy). 
Based on running that a few times, it seems to adds 1.5-2 % to the total pandas import time.  
> move roperator.py from pandas/core/ops to pandas/core, so it can be imported in pandas.core.computation.expressions without relying on the pandas.core.ops module, which in its turn means we can move the inline import of pandas.core.computation.expressions in pandas.core.ops.array_ops to a top-level import (better for performance for a function that is called repeatedly)

can we reorg a bit then, this *really* should be in ops logically. (not blocking here, just a further thought).

cc @jbrockmendel @jorisvandenbossche 
See the discussion above, `expressions.py` also contains code for `where`, which doesn't fully fit into ops