By Torilla


2018-12-06 15:00:25 8 Comments

I am currently implementing a class that can handle numeric data associated with physical units.

I would like to implement a way of calculating the square root of an instance. Assume that you have an instance of a class that has attributes value and name:

from math import sqrt

class Foo:
   def __init__(self, value, name)
      self.value = value
      self.name = name

   def __sqrt__(self):
      return sqrt(self.value)

I would like to implement a function similar to the magic methods like add(self, other) that would calculate the squareroot when I call the math.sqrt() function:

A = Foo(4, "meter")
root = math.sqrt(A)

should return call the A.sqrt() function.

3 comments

@John 2018-12-06 15:12:03

You can't without reassigning math.sqrt to a custom function. If you want to allow Foo to be cast to int or float you can implement __int__ and __float__ and cast before calling math.sqrt:

class Foo:
    def __init__(self, value, name)
        self.value = value
        self.name = name

    def __float__(self):
        return float(self.value)

    def __int__(self):
        return int(self.value)

A = Foo(4, "meter")
root = math.sqrt(float(A))

EDIT: According to the comments below, it seems that you can invoke math.sqrt(A) directly if Foo implements __float__ due to how the math module is implemented. I would still rather be explicit than implicit.

@DeepSpace 2018-12-06 15:18:40

Nice idea. but you don't have to convert A to float. sqrt will do that for you

@chepner 2018-12-06 15:20:57

Note that math.sqrt is somewhat of a special case, though; since math wraps a C library, it has no choice but to convert any Python object it receives to a machine float that can be processed by the underlying C library. In general, a Python function will not try to cast an argument to some other type.

@John 2018-12-06 15:46:28

@DeepSpace Is this behavior generalizable? It might be the case with CPython's math module, but it may not necessarily be so with other Python toolchains or perhaps other math modules and libraries.

@DeepSpace 2018-12-06 15:04:03

There's no trivial/out-of-the-box way to wire math.sqrt to call Foo.__sqrt__.

Just implement sqrt in Foo:

class Foo:
     ...
     def sqrt(self):
          return sqrt(self.value)

A = Foo(4, "meter")
root = A.sqrt()

If for some reason you insist, it can be hacked, but I don't see any reason why you would want to do that:

from math import sqrt

class Foo:
    def __init__(self, value, name):
        self.value = value
        self.name = name

    def __sqrt__(self):
        return sqrt(self.value)

orig_sqrt = sqrt

def my_sqrt(value):
    if isinstance(value, Foo):
        return orig_sqrt(value.value)
        # or return value.__sqrt__()
    else:
        return orig_sqrt(value)

sqrt = my_sqrt

A = Foo(4, "meter")
print(sqrt(A))
# 2.0
print(sqrt(4))
# 2.0

@David Culbreth 2018-12-06 15:13:56

Agreed. I highly suggest the naïve approach written in the first part of this answer.

@jxpp 2018-12-06 15:10:02

There's no magic method for sqrt like there is for other numerical functions.

You could define a sqrt method in your class, as pointed out in another answer.

What you could also do is make your own sqrt function which calls math.sqrt on an attribute of your class if passed an instance of that class.

import math

def sqrt(x):
    if isinstance(x, Foo):
        return math.sqrt(x.value)
    return math.sqrt(x)

This is however, rather hacky and wouldn't recommend it unless you absolutely need to call sqrt indiscriminately on a container of mixed types for some reason.

Related Questions

Sponsored Content

24 Answered Questions

28 Answered Questions

[SOLVED] Finding the index of an item given a list containing it in Python

  • 2008-10-07 01:39:38
  • Eugene M
  • 2934891 View
  • 2433 Score
  • 28 Answer
  • Tags:   python list

15 Answered Questions

[SOLVED] Does Python have a string 'contains' substring method?

31 Answered Questions

[SOLVED] How to get the current time in Python

  • 2009-01-06 04:54:23
  • user46646
  • 2396551 View
  • 2117 Score
  • 31 Answer
  • Tags:   python datetime time

53 Answered Questions

[SOLVED] Calling an external command in Python

25 Answered Questions

[SOLVED] How can I safely create a nested directory in Python?

24 Answered Questions

[SOLVED] Difference between append vs. extend list methods in Python

19 Answered Questions

[SOLVED] Creating a singleton in Python

15 Answered Questions

[SOLVED] What are metaclasses in Python?

8 Answered Questions

[SOLVED] Getting the class name of an instance?

Sponsored Content