Best way to "overload" function in python? [duplicate] - python

This question already has answers here:
Function overloading in Python: Missing [closed]
(5 answers)
Closed 7 years ago.
I am trying to do something like this in python:
def foo(x, y):
# do something at position (x, y)
def foo(pos):
foo(pos.x, pos.y)
So I want to call a different version of foo depending on the number of parameters I provide. This of course doesn't work because I redefined foo.
What would be the most elegant way of achieving this? I would prefer not to use named parameters.

Usually you'd either define two different functions, or do something like:
def foo(x, y = None):
if y is None:
x, y = x.x, x.y
# do something at position (x, y)
The option to define two different functions seems unwieldy if you're used to languages that have overloading, but if you're used to languages like Python or C that don't, then it's just what you do. The main problem with the above code in Python is that it's a bit awkward to document the first parameter, it doesn't mean the same in the two cases.
Another option is to only define the version of foo that takes a pos, but also supply a type for users:
Pos = collections.namedtuple('Pos', 'x y')
Then anyone who would have written foo(x,y) can instead write foo(Pos(x,y)). Naturally there's a slight performance cost, since an object has to be created.

You can use default parameters, but if you want use overloading in python, the best way to do this is:
from pytyp.spec.dispatch import overload
#overload
def foo(x,y):
#foo.overload
def foo(x, y,z):
Pytyp is a python package (you can download it from https://pypi.python.org/pypi/pytyp). It includes module pytyp.spec.dispatch, which contains decorators, like overload. If it is palced on method, this method will be called for all the overloaded methods..

There are a lot of things you could do, like named default parameters.
However, what it looks like you want is "multiple dispatch" and there's a number of implementations out of there of decorators to help you do that sort of thing. Here's one implementation that looks like:
>>> from multipledispatch import dispatch
>>> #dispatch(int, int)
... def add(x, y):
... return x + y
>>> #dispatch(Position)
... def add(pos):
... return "%s + %s" % (pos.x, pos.y)
>>> add(1, 2)
3
>>> pos = Position(3, 4)
>>> add(pos)
7
While #functools.singledispatch is coming to Python 3.4 I don't think that will work for your example as in one case you have multiple arguments.

What you're trying to achieve looks like a bad design, maybe consider sticking with different function names:
def do_something_by_coordinates(x, y):
pass
def do_something_by_position(pos):
do_something_by_coordinates(pos.x, pos.y)
Or you can use kwargs if you really need to:
Understanding kwargs in Python

One way by setting a default value:
def foo(x, y=None):
# now for example, you can call foo(1) and foo(1,2)
Inside foo you can check if y == None and have a different logic for the two cases.
Note that you can have a better design if you separate the functions, don't attempt to have the same function that accept both coordinates and position.

Related

How to "fool" duck typing in Python

Suppose I had a class A:
class A:
def __init__(self, x, y):
self.x = x
self.y = y
def sum(self):
return self.x + self.y
And I defined a factory method called factory:
def factory(x, y):
class B: pass
b = B()
setattr(b, 'x', x)
setattr(b, 'y', y)
B.__name__ = 'A'
return b
Now, If I do print(type(A(1, 2))) and print(type(factory(1, 2))) they will show that these are different types. And if I try to do factory(1, 2).sum() I'll get an exception. But, type(A).__name__ and type(factory(1, 2)).__name__ are equivalent and if I do A.sum(factory(1, 2)) I'll get 3, as if I was calling it using an A. So, my question is this:
What would I need to do here to make factory(1, 2).sum() work without defining sum on B or doing inheritance?
I think you're fundamentally misunderstanding the factory pattern, and possibly getting confused with how interfaces work in Python. Either that, or I am fundamentally confused by the question. Either way, there's some sorting out we need to do.
What would I need to do here to make factory(1, 2).sum() work without
defining sum on B or doing inheritance?
Just return an A instead of some other type:
def factory(x, y):
return A(x, y)
then
print(factory(1,2).sum())
will output 3 as expected. But that's kind of a useless factory...could just do A(x, y) and be done with it!
Some notes:
You typically use a "factory" (or factory pattern) when you have easily "nameable" types that may be non-trivial to construct. Consider how when you use scipy.interpolate.interp1d (see here) there's an option for kind, which is basically an enum for all the different strategies you might use to do an interpolation. This is, in essence, a factory (but hidden inside the function for ease of use). You could imagine this could be standalone, so you'd call your "strategy" factory, and then pass this on to the interp1d call. However, doing it inline is a common pattern in Python. Observe: These strategies are easy to "name", somewhat hard to construct in general (you can imagine it would be annoying to have to pass in a function that does linear interpolation as opposed to just doing kind='linear'). That's what makes the factory pattern useful...
If you don't know what A is up front, then it's definitely not the factory pattern you'd want to apply. Furthermore, if you don't know what you're serializing/deserializing, it would be impossible to call it or use it. You'd have to know that, or have some way of inferring it.
Interfaces in Python are not enforced like they are in other languages like Java/C++. That's the spirit of duck typing. If an interface does something like call x.sum(), then it doesn't matter what type x actually is, it just has to have a method called sum(). If it acts like the "sum" duck, quacks like the "sum" duck, then it is the "sum" duck from Python's perspective. Doesn't matter if x is a numpy array, or A, it'll work all the same. In Java/C++, stuff like that wont compile unless the compiler is absolutely certain that x has the method sum defined. Fortunately Python isn't like that, so you can even define it on the fly (which maybe you were trying to do with B). Either way, interfaces are a much different concept in Python than in other mainstream languages.
P.S.
But, type(A).__name__ and type(factory(1, 2)).__name__ are equivalent
Of course they are, you explicitly do this when you say B.__name__ = 'A'. So I'm not sure what you were trying to get at there...
HTH!

Can lambda work with *args as its parameter? [duplicate]

This question already has answers here:
Function chaining in Python
(6 answers)
Closed 6 years ago.
I am calculating a sum using lambda like this:
def my_func(*args):
return reduce((lambda x, y: x + y), args)
my_func(1,2,3,4)
and its output is 10.
But I want a lambda function that takes random arguments and sums all of them. Suppose this is a lambda function:
add = lambda *args://code for adding all of args
someone should be able to call the add function as:
add(5)(10) # it should output 15
add(1)(15)(20)(4) # it should output 40
That is, one should be able to supply arbitrary
number of parenthesis.
Is this possible in Python?
This is not possible with lambda, but it is definitely possible to do this is Python.
To achieve this behaviour you can subclass int and override its __call__ method to return a new instance of the same class with updated value each time:
class Add(int):
def __call__(self, val):
return type(self)(self + val)
Demo:
>>> Add(5)(10)
15
>>> Add(5)(10)(15)
30
>>> Add(5)
5
# Can be used to perform other arithmetic operations as well
>>> Add(5)(10)(15) * 100
3000
If you want to support floats as well then subclass from float instead of int.
The sort of "currying" you're looking for is not possible.
Imagine that add(5)(10) is 15. In that case, add(5)(10)(20) needs to be equivalent to 15(20). But 15 is not callable, and in particular is not the same thing as the "add 15" operation.
You can certainly say lambda *args: sum(args), but you would need to pass that its arguments in the usual way: add(5,10,20,93)
[EDITED to add:] There are languages in which functions with multiple arguments are handled in this sort of way; Haskell, for instance. But those are functions with a fixed number of multiple arguments, and the whole advantage of doing it that way is that if e.g. add 3 4 is 7 then add 3 is a function that adds 3 to things -- which is exactly the behaviour you're wanting not to get, if you want something like this to take a variable number of arguments.
For a function of fixed arity you can get Haskell-ish behaviour, though the syntax doesn't work so nicely in Python, just by nesting lambdas: after add = lambda x: lambda y: x+y you can say add(3)(4) and get 7, or you can say add(3) and get a function that adds 3 to things.
[EDITED again to add:] As Ashwini Chaudhary's ingenious answer shows, you actually can kinda do what you want by arranging for add(5)(10) to be not the actual integer 15 but another object that very closely resembles 15 (and will just get displayed as 15 in most contexts). For me, this is firmly in the category of "neat tricks you should know about but never ever actually do", but if you have an application that really needs this sort of behaviour, that's one way to do it.
(Why shouldn't you do this sort of thing? Mostly because it's brittle and liable to produce unexpected results in edge cases. For instance, what happens if you ask for add(5)(10.5)? That will fail with A.C.'s approach; PM 2Ring's approach will cope OK with that but has different problems; e.g., add(2)(3)==5 will be False. The other reason to avoid this sort of thing is because it's ingenious and rather obscure, and therefore liable to confuse other people reading your code. How much this matters depends on who else will be reading your code. I should add for the avoidance of doubt that I'm quite sure A.C. and PM2R are well aware of this, and that I think their answers are very clever and elegant; I am not criticizing them but offering a warning about what to do with what they've told you.)
You can kind of do this with a class, but I really wouldn't advise using this "party trick" in real code.
class add(object):
def __init__(self, arg):
self.arg = arg
def __call__(self, arg):
self.arg += arg
return self
def __repr__(self):
return repr(self.arg)
# Test
print(add(1)(15)(20)(4))
output
40
Initially, add(1) creates an add instance, setting its .args attribute to 1. add(1)(15) invokes the .call method, adding 15 to the current value of .args and returning the instance so we can call it again. This same process is repeated for the subsequent calls. Finally, when the instance is passed to print its __repr__ method is invoked, which passes the string representation of .args back to print.

Using setattr to freeze some parameters of a method [duplicate]

This question already has answers here:
Creating functions (or lambdas) in a loop (or comprehension)
(6 answers)
Closed 6 months ago.
in order to automatically generate parameterized tests, I am trying to add methods to a class in by freezing some parameters of an existing method. Here is the piece of Python 3 code
class A:
def f(self, n):
print(n)
params = range(10)
for i in params:
name = 'f{0}'.format(i)
method = lambda self: A.f(self, i)
setattr(A, name, method)
However, the following lines then produce rather disappointing output
a = A()
a.f0()
prints "9" (instead of "0"). I must be doing something wrong, but I can't see what. Can you help ?
Thanks a lot
Edit: this question is indeed a duplicate. I would like to acknowledge the quality of all comments, which go much deeper than the raw answer.
Try
method = lambda self, i=i: A.f(self, i)
because otherwise when you call the method i's value may have changed
The best way to "freeze" parameters in Python is to use functools.partial. It's roughly equivalent to warwaruk's lambda version, but if you have a function with lots of arguments yet only want to freeze one or two of them (or if you only know certain arguments and don't care about the rest) using partial is more elegant as you only specify the arguments you want to freeze rather than having to repeat the whole function signature in the lambda.
An example for your program:
class A:
def f(self, n):
print(n)
from functools import partial
for i in range(10): # params
setattr(A, 'f{0}'.format(i), partial(A.f, n=i))
Depending on which version of Python 3 you're using, you may not need to include the 0 in the string format placeholder; starting with 3.1, iirc, it should be automatically substituted.

What exactly is "lambda" in Python? [duplicate]

This question already has answers here:
What is `lambda` in Python code? How does it work with `key` arguments to `sorted`, `sum` etc.?
(4 answers)
Closed 6 months ago.
I want to know what exactly is lambda in python? and where and why it is used.
thanks
Lambda is more of a concept or programming technique then anything else.
Basically it's the idea that you get a function (a first-class object in python) returned as a result of another function instead of an object or primitive type. I know, it's confusing.
See this example from the python documentation:
def make_incrementor(n):
return lambda x: x + n
f = make_incrementor(42)
f(0)
>>> 42
f(1)
>>> 43
So make_incrementor creates a function that uses n in it's results. You could have a function that would increment a parameter by 2 like so:
f2 = make_incrementor(2)
f2(3)
>>> 5
This is a very powerful idea in functional programming and functional programming languages like lisp & scheme.
Hope this helps.
Lambdas are not anonymous functions. Lambdas are anonymous expressions.
They're accessed like functions, but they're not the same thing. Functions allow complex tasks: flow control, variable declarations and lists of statements containing expressions. Expressions are merely one part of a function, and that's what lambdas give you. They're severely limited compared to functions.
Python does not support anonymous functions. For examples of languages that do, see Javascript and Lua.
(Note: It's correct to call lambdas anonymous functions in functional languages, where the mathematical definition of "function" is used, but in procedural languages the word has a very different meaning than in mathematics.)
Lambda functions are not a Python specific concept, but are a general programming term for anonymous function, i.e. functions without a name. In Python they are commonly used where you need to pass a simple function as a parameter to another function.
The sort method on lists takes a parameter key which is a function that is used to calculate the value the list is sorted on. Imagine you are sorting a list of two element tuples, and you want to sort the list based on the first element. You need to pass a function to key which returns the first element. You could do this:
def first_element(x):
return x[0]
my_list.sort(key=first_element)
or, much more concisely you can do:
my_list.sort(key=lambda x: x[0])
The lambda construct is a shorter way to define a simple function that calculates a single expression. The def statement can be inconvenient and make the code longer, broken up and harder to read through. The functions created by the two are virtually the same by the way they work, the difference is that lambda is limited to a single expression the value of which is returned and that def assigns a name to the function and adds it to the local variables by that same name. Also lambda can be used in an expression directly, while def is a statement.
def f(x, y):
return x + y
Would give you almost the same result as
f = lambda x, y: x + y
And you can use it directly in an expression
g(5, 6, helper=lambda x, y: x + y)
which with def would be less concise
def helper_function(x + y):
return x + y
g(5, 6, helper=helper_function)
lambda is a way of defining an anonymous in-line function to accomplish some task versus defining it with the def keyword and calling it. Think of it as a shorthand you can use when you won't need to reuse a function. Anywhere you use lambda, you could substitute an explicitly called function: it's use is completely optional and left to the programmer as a matter of coding style.
Example code (without lambda):
def numSquared(num):
return num**2
for i in range(1,11):
print numSquared(i)
Example code (with lambda):
for i in range(1,11):
print (lambda x: x**2)(i)
A good beginner's discussion of lambda:
DiveIntPython.org - Lambda
lambda allows you define simple, unnamed functions inline with your code, e.g. as an argument. This is useful if you plan to use the function only once, and therefore don't want to clutter your code with a named function.
Let's say you have a list of numbers (thelist), and you want to get a list of the same length, with each number doubled. Rather than defining a times_two function, you could do something like this:
map(lambda x: x * 2, thelist)
lambda also makes Currying more convenient.
The first linked returned by googling "python lambda" points to a page whose first paragraphs answer your question. I could copy & paste the content it, but I think it's unfair :)
It's an inline anonymous function.
lambda is an anonymous function, usually used for something quick that needs computing.
Example (This is used in a LexYacc command parser):
assign_command = lambda dictionary, command: lambda command_function: dictionary.setdefault(command, command_function)
This is a decorator. Put before a command we'd have from the LexYacc parser:
#assign_command(_command_handlers, 'COMMAND')
This essentially builds a python script from the LexYacc language defined.
Or, a bit simpler:
`x = lambda x: return x > 0 and x & (x-1) == 0
Lambda can be interpreted intuitively as algebra function.
Suppose a basic algebra y = x**2 + 1
if typed directly,
>>> y = x**2 + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
error occurs and reports that variable 'x' should be defined firstly.
nevertheless,'x' is unknown, how can it be pre-defined.
Lambda helps:
python
>>> y = lambda x: x**2 + 1 # no errors reports
>>> y(3)
10
That's core about lambda,
It's in programming language to write an inline function.
Lambda is an anonymous function in Python programming language, instead of bearing a def statement in the front it is simply called and written lambda.
def mult2(x):
return x*2
print(mult2(2))
# returns 4
Exactly same you can do with a lambda function.
lam = lambda x : x*2
print(lam(2))
# returns 4
For more details you can look up in this blog post.
http://friendlypython.herokuapp.com/2017/1/anonymous-function-lambda/ or here
I would like to explain this with a little layman approach in terms of the usage perspective, since all the technical points are already covered.
A lambda function is just like any other function, only thing that makes it different (other than the syntax and the fact that it can't be reused), is that it is used when we want to quickly write a function which takes an argument and just returns a value using only one expression.
For instance:
If all that a function does is take a argument and add 1 to it then using a lambda function is a better approach than a normal function.
But if your function requires more than one line of processing before returning the value, then we need to use a normal function definition and then call it.

Is nested function a good approach when required by only one function? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Let's say that a function A is required only by function B, should A be defined inside B?
Simple example. Two methods, one called from another:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
In Python we can declare def inside another def. So, if method_b is required for and called only from method_a, should I declare method_b inside method_a? like this :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Or should I avoid doing this?
>>> def sum(x, y):
... def do_it():
... return x + y
... return do_it
...
>>> a = sum(1, 3)
>>> a
<function do_it at 0xb772b304>
>>> a()
4
Is this what you were looking for? It's called a closure.
You don't really gain much by doing this, in fact it slows method_a down because it'll define and recompile the other function every time it's called. Given that, it would probably be better to just prefix the function name with underscore to indicate it's a private method -- i.e. _method_b.
I suppose you might want to do this if the nested function's definition varied each time for some reason, but that may indicate a flaw in your design. That said, there is a valid reason to do this to allow the nested function to use arguments that were passed to the outer function but not explicitly passed on to them, which sometimes occurs when writing function decorators, for example. It's what is being shown in the accepted answer although a decorator is not being defined or used.
Update:
Here's proof that nesting them is slower (using Python 3.6.1), although admittedly not by much in this trivial case:
setup = """
class Test(object):
def separate(self, arg):
some_data = self._method_b(arg)
def _method_b(self, arg):
return arg+1
def nested(self, arg):
def method_b2(self, arg):
return arg+1
some_data = method_b2(self, arg)
obj = Test()
"""
from timeit import Timer
print(min(Timer(stmt='obj.separate(42)', setup=setup).repeat())) # -> 0.24479823284461724
print(min(Timer(stmt='obj.nested(42)', setup=setup).repeat())) # -> 0.26553459700452575
Note I added some self arguments to your sample functions to make them more like real methods (although method_b2 still isn't technically a method of the Test class). Also the nested function is actually called in that version, unlike yours.
Generally, no, do not define functions inside functions.
Unless you have a really good reason. Which you don't.
Why not?
It prevents easy hooks for unit testing. You are unit testing, aren't you?
It doesn't actually obfuscate it completely anyway, it's safer to assume nothing in python ever is.
Use standard Python automagic code style guidelines to encapsulate methods instead.
You will be needlessly recreating a function object for the identical code every single time you run the outer function.
If your function is really that simple, you should be using a lambda expression instead.
What is a really good reason to define functions inside functions?
When what you actually want is a dingdang closure.
A function inside of a function is commonly used for closures.
(There is a lot of contention over what exactly makes a closure a closure.)
Here's an example using the built-in sum(). It defines start once and uses it from then on:
def sum_partial(start):
def sum_start(iterable):
return sum(iterable, start)
return sum_start
In use:
>>> sum_with_1 = sum_partial(1)
>>> sum_with_3 = sum_partial(3)
>>>
>>> sum_with_1
<function sum_start at 0x7f3726e70b90>
>>> sum_with_3
<function sum_start at 0x7f3726e70c08>
>>> sum_with_1((1,2,3))
7
>>> sum_with_3((1,2,3))
9
Built-in python closure
functools.partial is an example of a closure.
From the python docs, it's roughly equivalent to:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
(Kudos to #user225312 below for the answer. I find this example easier to figure out, and hopefully will help answer #mango's comment.)
It's actually fine to declare one function inside another one. This is specially useful creating decorators.
However, as a rule of thumb, if the function is complex (more than 10 lines) it might be a better idea to declare it on the module level.
I found this question because I wanted to pose a question why there is a performance impact if one uses nested functions. I ran tests for the following functions using Python 3.2.5 on a Windows Notebook with a Quad Core 2.5 GHz Intel i5-2530M processor
def square0(x):
return x*x
def square1(x):
def dummy(y):
return y*y
return x*x
def square2(x):
def dummy1(y):
return y*y
def dummy2(y):
return y*y
return x*x
def square5(x):
def dummy1(y):
return y*y
def dummy2(y):
return y*y
def dummy3(y):
return y*y
def dummy4(y):
return y*y
def dummy5(y):
return y*y
return x*x
I measured the following 20 times, also for square1, square2, and square5:
s=0
for i in range(10**6):
s+=square0(i)
and got the following results
>>>
m = mean, s = standard deviation, m0 = mean of first testcase
[m-3s,m+3s] is a 0.997 confidence interval if normal distributed
square? m s m/m0 [m-3s ,m+3s ]
square0 0.387 0.01515 1.000 [0.342,0.433]
square1 0.460 0.01422 1.188 [0.417,0.503]
square2 0.552 0.01803 1.425 [0.498,0.606]
square5 0.766 0.01654 1.979 [0.717,0.816]
>>>
square0 has no nested function, square1 has one nested function, square2 has two nested functions and square5 has five nested functions. The nested functions are only declared but not called.
So if you have defined 5 nested funtions in a function that you don't call then the execution time of the function is twice of the function without a nested function. I think should be cautious when using nested functions.
The Python file for the whole test that generates this output can be found at ideone.
So in the end it is largely a question about how smart the python implementation is or is not, particularly in the case of the inner function not being a closure but simply an in function needed helper only.
In clean understandable design having functions only where they are needed and not exposed elsewhere is good design whether they be embedded in a module, a class as a method, or inside another function or method. When done well they really improve the clarity of the code.
And when the inner function is a closure that can also help with clarity quite a bit even if that function is not returned out of the containing function for use elsewhere.
So I would say generally do use them but be aware of the possible performance hit when you actually are concerned about performance and only remove them if you do actual profiling that shows they best be removed.
Do not do premature optimization of just using "inner functions BAD" throughout all python code you write. Please.
It's just a principle about exposure APIs.
Using python, It's a good idea to avoid exposure API in outer space(module or class), function is a good encapsulation place.
It could be a good idea. when you ensure
inner function is ONLY used by outer function.
insider function has a good name to explain its purpose because the code talks.
code cannot directly understand by your colleagues(or other code-reader).
Even though, Abuse this technique may cause problems and implies a design flaw.
Just from my exp, Maybe misunderstand your question.
It's perfectly OK doing it that way, but unless you need to use a closure or return the function I'd probably put in the module level. I imagine in the second code example you mean:
...
some_data = method_b() # not some_data = method_b
otherwise, some_data will be the function.
Having it at the module level will allow other functions to use method_b() and if you're using something like Sphinx (and autodoc) for documentation, it will allow you to document method_b as well.
You also may want to consider just putting the functionality in two methods in a class if you're doing something that can be representable by an object. This contains logic well too if that's all you're looking for.
You can use it to avoid defining global variables. This gives you an alternative for other designs. 3 designs presenting a solution to a problem.
A) Using functions without globals
def calculate_salary(employee, list_with_all_employees):
x = _calculate_tax(list_with_all_employees)
# some other calculations done to x
pass
y = # something
return y
def _calculate_tax(list_with_all_employees):
return 1.23456 # return something
B) Using functions with globals
_list_with_all_employees = None
def calculate_salary(employee, list_with_all_employees):
global _list_with_all_employees
_list_with_all_employees = list_with_all_employees
x = _calculate_tax()
# some other calculations done to x
pass
y = # something
return y
def _calculate_tax():
return 1.23456 # return something based on the _list_with_all_employees var
C) Using functions inside another function
def calculate_salary(employee, list_with_all_employees):
def _calculate_tax():
return 1.23456 # return something based on the list_with_a--Lemployees var
x = _calculate_tax()
# some other calculations done to x
pass
y = # something
return y
Solution C) allows to use variables in the scope of the outer function without having the need to declare them in the inner function. Might be useful in some situations.
Do something like:
def some_function():
return some_other_function()
def some_other_function():
return 42
if you were to run some_function() it would then run some_other_function() and returns 42.
EDIT: I originally stated that you shouldn't define a function inside of another but it was pointed out that it is practical to do this sometimes.
Function In function python
def Greater(a,b):
if a>b:
return a
return b
def Greater_new(a,b,c,d):
return Greater(Greater(a,b),Greater(c,d))
print("Greater Number is :-",Greater_new(212,33,11,999))

Categories

Resources