473,382 Members | 1,743 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

how to overload sqrt in a module?

I would like to write a module that provides some mathematical functions
on top of those defined in math, cmath etc. but I would like to make it
work with "any" type that overloads the math functions.

Thus, I would like to write:

module_f.py
----
def f(x):
""" Compute sqrt of x """
return sqrt(x)
from math import *
import module_f
module_f.f(3) Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "module_f.py", line 2, in f
return sqrt(x)
NameError: global name 'sqrt' is not defined

I understand why sqrt is not in scope, but my question is: what is the
best way to do this?

Here is one fairly ugly solution:

module_g.py
-----------
def g(x,math):
return math.sqrt(x)
import math, cmath, module_g
module_g.g(2,math) 1.4142135623730951 module_g.g(-2,cmath)

1.4142135623730951j

I am sure there is a better way of doing this that makes use of the
type of the argument (Dynamical scoping would solve the
problem but we don't want to go there...). Note that the following
function would work fine

def f(x):
return abs(x)

because of the special member __abs__ attached to the type. There is no
corresponding member for sqrt, sin etc.

What is the "proper" pythonic way to do this?

Michael.
Mar 3 '06 #1
13 3737
Michael McNeil Forbes wrote:
I would like to write a module that provides some mathematical functions
on top of those defined in math, cmath etc. but I would like to make it
work with "any" type that overloads the math functions.

Thus, I would like to write:

module_f.py
----
def f(x):
""" Compute sqrt of x """
return sqrt(x)
from math import *
import module_f
module_f.f(3)


Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "module_f.py", line 2, in f
return sqrt(x)
NameError: global name 'sqrt' is not defined

I understand why sqrt is not in scope, but my question is: what is the
best way to do this?


You need to import math in the module that uses it. Imports in one
module don't (in general) affect the variables available in another module.

module_f.py
----
from math import sqrt # more explicit than from math import *
def f(x):
""" Compute sqrt of x """
return sqrt(x)

Kent
Mar 3 '06 #2
>> I would like to write a module that provides some mathematical functions on
top of those defined in math, cmath etc. but I would like to make it work
with "any" type that overloads the math functions.

Thus, I would like to write:

module_f.py
----
def f(x):
""" Compute sqrt of x """
return sqrt(x)
> from math import *
> import module_f
> module_f.f(3)


Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "module_f.py", line 2, in f
return sqrt(x)
NameError: global name 'sqrt' is not defined

I understand why sqrt is not in scope, but my question is: what is the best
way to do this?


You need to import math in the module that uses it. Imports in one module
don't (in general) affect the variables available in another module.

module_f.py
----
from math import sqrt # more explicit than from math import *
def f(x):
""" Compute sqrt of x """
return sqrt(x)

Kent


I know, but the point is that I want to allow the user of the module to be
able to specify which sqrt function should be used depending on the type
of x. Importing math in the module would prevent the user from using f()
with complex types (or dimensioned types for another example).

That is why I suggested the ugly, but functional solution

module_g.py
-----------
def g(x,a_math):
"""Compute sqrt of x using a_math.sqrt)
return a_math.sqrt(x)

The user can at least specify to use cmath instead of math:
import cmath, module_g
module_g.g(8j,cmath)

(2+2j)

Michael.

Mar 3 '06 #3
Michael McNeil Forbes wrote:
Here is one fairly ugly solution:

module_g.py
-----------
def g(x,math):
return math.sqrt(x)

import math, cmath, module_g
module_g.g(2,math)
1.4142135623730951
module_g.g(-2,cmath)


1.4142135623730951j

I am sure there is a better way of doing this that makes use of the
type of the argument (Dynamical scoping would solve the
problem but we don't want to go there...). Note that the following
function would work fine

def f(x):
return abs(x)

because of the special member __abs__ attached to the type. There is no
corresponding member for sqrt, sin etc.

What is the "proper" pythonic way to do this?


Use the appropriate library which already implements the features you want.

In [8]: class A(object):
...: def __init__(self, x):
...: self.x = x
...: def sqrt(self):
...: return 2*self.x
...:
...:

In [9]: a = A(10)

In [10]: import numpy

In [11]: numpy.sqrt(a)
Out[11]: 20

In [12]: numpy.sqrt(10)
Out[12]: 3.1622776601683795

In [13]: numpy.sqrt(10j)
Out[13]: (2.2360679774997898+2.2360679774997898j)

--
Robert Kern
ro*********@gmail.com

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter

Mar 3 '06 #4
> Michael McNeil Forbes wrote:
Here is one fairly ugly solution:

module_g.py
-----------
def g(x,math):
return math.sqrt(x)

> import math, cmath, module_g
> module_g.g(2,math)
1.4142135623730951
> module_g.g(-2,cmath)


1.4142135623730951j

What is the "proper" pythonic way to do this?

On Thu, 2 Mar 2006, Robert Kern wrote:
Use the appropriate library which already implements the features you want.

In [8]: class A(object):
...: def __init__(self, x):
...: self.x = x
...: def sqrt(self):
...: return 2*self.x
...:
...:

In [9]: a = A(10)

In [10]: import numpy

In [11]: numpy.sqrt(a)
Out[11]: 20

In [12]: numpy.sqrt(10)
Out[12]: 3.1622776601683795

In [13]: numpy.sqrt(10j)
Out[13]: (2.2360679774997898+2.2360679774997898j)

--
Robert Kern


Thanks. This solution is essentially to make sure that all "numeric"
objects have .sqrt etc. members, and then use a library which check
against builtin types and custom types with these extensions.

That works, as long as the appropriate library exists (or I write it
myself) (and this works in my case: I did not realize that the numpy/scipy
functions worked this way.)

Are there any other more generic solutions (without having to write
"custom" functions like numpy.sqrt)?

Michael
Mar 3 '06 #5
Michael McNeil Forbes wrote:
Are there any other more generic solutions (without having to write
"custom" functions like numpy.sqrt)?


No. *Someone* always has to write those "custom" functions. In the case of len()
and abs(), that someone was Guido. For numpy.sqrt(), that someone was Travis
Oliphant. For anything else you want, that someone is probably you.

--
Robert Kern
ro*********@gmail.com

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter

Mar 3 '06 #6
>> Are there any other more generic solutions (without having to write
"custom" functions like numpy.sqrt)?


No. *Someone* always has to write those "custom" functions. In the case of len()
and abs(), that someone was Guido. For numpy.sqrt(), that someone was Travis
Oliphant. For anything else you want, that someone is probably you.


Thanks Guido! Thanks Travis:-)

What I was thinking was: is there some way to pass a parameter to the
module on import so that the module can then use the correct environment.

If I could pass a dictionary to the module with all of the overloaded
functions, then they could become part of the module's environment and
used appropriately. I could not find a way of passing such a dictionary.

Michael.
Mar 3 '06 #7
> On Thu, 2 Mar 2006 16:12:53 -0800, Michael McNeil Forbes wrote:
I would like to write a module that provides some mathematical functions
on top of those defined in math, cmath etc. but I would like to make it
work with "any" type that overloads the math functions.
On Fri, 3 Mar 2006, Dennis Lee Bieber wrote: Since Python doesn't dispatch based on parameter types, there are
only two choices that I can see...

Either the CALLER already knows what the arguments are, and has
coded an explicit call to the version of the function desired...
The caller does know in my case, but wants to reuse old code that performs
a complicated computation using the standard math functions. I was
thinking that maybe there was some way for the caller to pass the
appropriate functions to the module on import, but could not find a way of
doing this.
OR, the caller imports and calls your special module, and your
special module has to import ALL possible override modules and supply a
function that determines which of the modules is to be used...


This is essentially what numpy.sqrt() etc. does as pointed out by Robert
Kern. The numpy.sqrt() seems to check if the argument is real, complex,
or some other type and calls either math.sqrt, cmath.sqrt or x.sqrt()
appropriately. This works for my problem: I just wondered if there was a
more generic solution without having to do this work.

Thanks,
Michael.
Mar 3 '06 #8
On Thu, 02 Mar 2006 19:24:48 -0800, mforbes wrote:

[snip]
I know, but the point is that I want to allow the user of the module to be
able to specify which sqrt function should be used depending on the type
of x. Importing math in the module would prevent the user from using f()
with complex types (or dimensioned types for another example).


If I don't misunderstood the problem, you can define an "init" method for
your module_g

(code not tested)

module_g.py
-----------

_functions = {}
def init(mathmodule):
_function['sqrt'] = getattr(mathmodule, 'sqrt', None)

def _get(name):
try:
return _functions[name]
except KeyError:
raise TypeError("you have to initialize module_g")

def sqrt(x):
return _get('sqrt')(x)

main.py
-------

import math
import module_g

module_g.init(math)
print module_g.sqrt(2)
HTH

Mar 3 '06 #9
On Thu, 02 Mar 2006 22:35:51 -0800, Michael McNeil Forbes wrote:
What I was thinking was: is there some way to pass a parameter to the
module on import so that the module can then use the correct environment.

If I could pass a dictionary to the module with all of the overloaded
functions, then they could become part of the module's environment and
used appropriately. I could not find a way of passing such a dictionary.


Not on import, but you can do this:
import my_module
my_module.set_environment("math") # or cmath, or numeric, or whatever

Your my_module will be like this:

# Warning: untested code.
ENVIRON = None # global variables sometimes have their uses

def f(x):
if ENVIRON is None:
raise ValueError("Uninitialised module!")
# or use a custom exception
return ENVIRON.sqrt(x)

def set_environment(name):
global ENVIRON
ENVIRON = __import__(name)
Does this help?
--
Steven.

Mar 3 '06 #10
On Fri, 3 Mar 2006, david mugnai wrote:

[snip]

If I don't misunderstood the problem, you can define an "init" method for
your module_g

(code not tested)

module_g.py
-----------

_functions = {}
def init(mathmodule):
_function['sqrt'] = getattr(mathmodule, 'sqrt', None)

def _get(name):
try:
return _functions[name]
except KeyError:
raise TypeError("you have to initialize module_g")

def sqrt(x):
return _get('sqrt')(x)

main.py
-------

import math
import module_g

module_g.init(math)
print module_g.sqrt(2)


Thanks, this gets me close. Is there anything really bad about the
following? It works exactly as I would like, but I don't want to get in
trouble down the road:

module_f
--------
import math as my_math

def set_math(custom_math):
globals()['my_math'] = custom_math

def f(x):
return my_math.sqrt(x)
import module_f
module_f.f(2) 1.4142135623730951 import cmath
module_f.set_math(cmath)
module_f.f(2j)

(1+1j)

Or, if one wants to use the "from __ import *" form:

from math import *

def set_math(custom_math):
globals().update(custom_math.__dict__)

def f(x):
return sqrt(x)

Michael
Mar 5 '06 #11
On Fri, 3 Mar 2006, Steven D'Aprano wrote:
... you can do this:

import my_module
my_module.set_environment("math") # or cmath, or numeric, or whatever

Your my_module will be like this:

# Warning: untested code.
ENVIRON = None # global variables sometimes have their uses

def f(x):
if ENVIRON is None:
raise ValueError("Uninitialised module!")
# or use a custom exception
return ENVIRON.sqrt(x)

def set_environment(name):
global ENVIRON
ENVIRON = __import__(name)
Does this help?


Yes. However, this raises a question: Is this any different than
directly modifying the globals, or is it just syntactic sugar.

import math as my_math

def set_environment(name):
globals()['ENVIRON'] = __import__(name)

Thanks,
Michael.
Mar 5 '06 #12
Michael McNeil Forbes wrote:
Is there anything really bad about the
following? It works exactly as I would like, but I don't want to get in
trouble down the road:

module_f
--------
import math as my_math

def set_math(custom_math):
globals()['my_math'] = custom_math
This seems clearer to me:
def set_math(custom_math):
global my_math
my_math = custom_math
Or, if one wants to use the "from __ import *" form:

from math import *

def set_math(custom_math):
globals().update(custom_math.__dict__)


This will cause interesting trouble if custom_math doesn't implement all
the functions you use from math.

Kent
Mar 5 '06 #13
On Sat, 04 Mar 2006 23:07:12 -0800, Michael McNeil Forbes wrote:
On Fri, 3 Mar 2006, Steven D'Aprano wrote:
... you can do this:

import my_module
my_module.set_environment("math") # or cmath, or numeric, or whatever

Your my_module will be like this:

# Warning: untested code.
ENVIRON = None # global variables sometimes have their uses

def f(x):
if ENVIRON is None:
raise ValueError("Uninitialised module!")
# or use a custom exception
return ENVIRON.sqrt(x)

def set_environment(name):
global ENVIRON
ENVIRON = __import__(name)
Does this help?
Yes. However, this raises a question: Is this any different than
directly modifying the globals, or is it just syntactic sugar.


The keyword "global" instructs Python to make all references to the
following name come from the global namespace. It is the correct way to
do it (but not necessarily the *only* correct way, or *always* the
correct way). In something as tiny as your example:
def set_environment(name):
globals()['ENVIRON'] = __import__(name)


it may not make any practical difference which method you use. But in
larger, more complex code, you are creating a rod for your own back. Try
running these three functions, and explain the difference in their
behaviour.

def f1():
global parrot
parrot = 3
parrot += 1
print "parrot is %d" % parrot

def f2():
globals()["parrot"] = 3
globals()["parrot"] += 1
print "parrot is %d" % parrot

def f3():
globals()["parrot"] = 3
parrot += 1
print "parrot is %d" % parrot
Directly modifying the globals is playing around with Python's internals.
You are allowed to do that, and sometimes it is the right thing to do,
otherwise Guido wouldn't have made globals() writable.

E.g. you have code where you want -- heaven knows why -- a name to refer
to both a local and a global variable. This will work:

def func():
x = 5 # x is local
globals()['x'] = 3 # but this x is global
I don't know whether writing to globals() is guaranteed to work for all
variants of Python (CPython, Jython, PyPy, IronPython ... ) or if it is
likely to change in Python 3. But even if modifying globals() is
officially allowed, it still has a whiff of the sort of code-smell that
Joel Spolsky talks about:

http://www.joelonsoftware.com/articles/Wrong.html

In my opinion, manipulating globals() is one of those things that ring
warning bells in my head. It might not be *wrong*, exactly, but I'll want
to pay extra attention to any function that does that.
--
Steven.

Mar 5 '06 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Equis Uno | last post by:
Hi there, I just figured out how to use __add__() to overload the "+" operator for objects of a class. According to googel queries, I see other functions available to me for overloading other...
10
by: pauldepstein | last post by:
I am writing a program which will use the ceiling and floor of square roots. If a positive integer is an exact square (and is not overly huge), does sqrt return an integer-valued real? Or...
7
by: Aric | last post by:
Hi, I'm a bit new to programming in general, really I've just picked it up as a hobby, and so I've started by reading "Practical C Programming" by Steve Oualline. Things have been going fine in...
13
by: Vladimir Granitsky | last post by:
Hi guys, Please, look at the code below and try to step into it. The compiled code calls the loosely typed method public void Method1(object o) !?!? Am I right that C# compiler does wrong...
12
by: Thomas Zhu | last post by:
hello all, n is an 32bit-integer, how to calculate sqrt(n) I know high(n) is the the value, but how to use bit operation to implement this function. thanks in advance. yours Yin
13
by: siggi | last post by:
Hi all, this is a newbie question on : Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) on win32 PC with WinXP In http://www.python.org/doc/2.3.5/lib/module-math.html I read:
30
by: copx | last post by:
I am writing a program which uses sqrt() a lot. A historically very slow function but I read on CPUs with SSE support this is actually fast. Problem: C's sqrt() (unlike C++ sqrt()) is defined to...
13
by: =?Utf-8?B?RXRoYW4gU3RyYXVzcw==?= | last post by:
Hi, Why does Math.Sqrt() only accept a double as a parameter? I would think it would be just as happy with a decimal (or int, or float, or ....). I can easily convert back and forth, but I am...
6
by: Blue sky | last post by:
Hi ,I think the follow program is right in logical But why the compiler output :"square:declared identifier" #include<stdio.h> #include<math.h> int main() { double x1;
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.