0

I have a file, which defines

def foo(x):
   return round(x)

Here round is the python built-in function.

Now, I would like to call this function with a numpy array. Numpy has a round function, too. Unfortunately, there are issues (e.g. #11557)

import numpy as np

foo(7.6)
foo(np.array([7.6]))       # works with python2 + np_1.14.0, not with 3.6.9 + np_1.14.5
foo(np.array([7.6, 8.9]))  # TypeError: type numpy.ndarray doesn't define __round__ method

Are there possibilities to replace the function round with np.round inside the foo function? Some patch like round = np.round before import or foo.round = np.round after import?

Edit: I'm looking for a solution without modifing the file.

3 Answers3

0

Yes sure you can do it. Just check class of the x using isinstance

import numpy as np

def foo(x):
    if isinstance(x, np.ndarray):
        return x.round()
    return round(x)


print(foo(7.6))
print(foo(np.array([7.6])))
print(foo(np.array([7.6, 8.9])))
Anton Pomieshchenko
  • 2,051
  • 2
  • 10
  • 24
0

A subclass is a work around (as @Anton Pomieshchenko commented)

class Array(np.ndarray):
    def __new__(cls, array, **kwargs):
        return np.asarray(array, **kwargs).view(cls)
    def __round__(self):
        return np.round(self.data)

foo(Array([7.6, 8.9]))

Works for python 3, while in python 2 I get TypeError: only size-1 arrays can be converted to Python scalars.

I without success I tried also np.__round__ = np.round (TypeError: only size-1 arrays can be converted to Python scalars) or np.ndarray.__round__ = np.round (TypeError: can't set attributes of built-in/extension type 'numpy.ndarray').

0

This requires to modify the file, but the file remains independent of numpy. The modified file bar.py is

def foo(x):
   return foo.round(x)

foo.round = round

Then the round function can be replaced after import

from bar import foo
import numpy as np
foo(7.6)
foo.round = np.round
foo([7.6, 8.9])       # 

Inspired by https://stackoverflow.com/a/338420/11769765.

Alternatively, using

from builtins import round

def foo(x):
   return round(x)

for bar.py, makes the round method accessbile

from bar import foo
import bar
import numpy as np
foo(7.6)           # 8
bar.round = np.round
foo([7.6, 8.9])    # array([8., 9.])