Python Forum
Defining multiple functions in the same def process
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Defining multiple functions in the same def process
#1
I'm trying to define a function which would give multiple value outputs after some tedious calculation. Based on my current knowledge the best I can do now is to let it return a dictionary. Below is a simplified version.

def external(a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):        
            G.append(0 if min(b[i], hval) < max(a[i], lval) else min(b[i], hval) - max(a[i], lval)) 
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])
        return dict([('ratio', max(E[:-yr])), ('index', E.index(max(E[:-yr])))])
Otherwise I will have to copy the function like the following as I don't know how to define multiple functions base on the same definition process, but this obviously would not be the best choice of any programmer.

def externalratio(a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):        
            G.append(0 if min(b[i], hval) < max(a[i], lval) else min(b[i], hval) - max(a[i], lval)) 
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])
        return max(E[:-yr]))

def externalindex(a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):        
            G.append(0 if min(b[i], hval) < max(a[i], lval) else min(b[i], hval) - max(a[i], lval)) 
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])
        return E.index(max(E[:-yr]))
However the dictionary way becomes problematic when I further write functions on top of that. First that's not very user-friendly and second it would return an error upon further calculation in a real example (to simplify the case that's not shown here), which strangely would not happen in the single definition way that doesn't involve dictionary return.

def maxexternalratio(a, b, yr):
    Etemp = []
    for i in range(len(a)):
        for j in range(len(a)):
             Etemp.append(external(a, b, a[i], b[j], yr)['ratio'])
    return max(Etemp)
So how can I define multiple functions which are results of the same calculation process, like "external.ratio" and "external.index", without requiring to copy the same thing multiple times? Any help would be very appreciated.
Reply
#2
You can return a tuple of results
def external(a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):        
            G.append(0 if min(b[i], hval) < max(a[i], lval) else min(b[i], hval) - max(a[i], lval)) 
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])
        ratio = max(E[:-yr])
        return ratio, E.index(ratio)

ratio, index = external(a, b, lval, hval, yr)
Reply
#3
(Aug-08-2020, 06:10 PM)Yoriz Wrote: You can return a tuple of results

Thanks for the input. In that case I would have to assign "ratio" and "index" to a single result only, because ratio and index are not function themselves. Line 10 only works when I actually input some values to a, b, lval, hval and yr.

Seems I cannot separate the ratio and index functions in a neat and elegant way? Any further insight would be appreciated.

def external(a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):        
            G.append(0 if min(b[i], hval) < max(a[i], lval) else min(b[i], hval) - max(a[i], lval)) 
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])
        ratio = max(E[:-yr])
        return ratio, E.index(ratio)

L = [1.238623532,1.315924461,1.430787909,0.65436604,0.78646411,1.551692625,1.143410924,1.044302349,1.12971696,1.007285185,1.009553518,0.646888596,1.027950548,0.950471257,1.048221271,1.070840989]
H = [1.514019069,1.662165686,3.098538659,3.148539828,2.248779234,2.542734245,2.312232392,1.855592543,1.99976568,1.715706499,2.111987812,1.74066515,2.038750404,2.058942087,2.0941254,1.498883955]
print(external(L, H, 1.00955235351066, 2.03874956866074, 6)[0])

ratio, index = external(L, H, 1.00955235351066, 2.03874956866074, 6)
print(ratio)
Reply
#4
Is what you really want to do to write a generic function where the thing that varies is a function that's called inside? If so, look into the idea of higher order functions - in Python, functions are values and can be passed around like other things. A higher order function is one that takes another function as a parameter (or returns one, but the former case sounds more useful for you right now). An example of such a thing is the built in map function:

>>> xs = [1, 2, 3]
>>> list(map(lambda x: x * 2, xs))
[2, 4, 6]
>>> words = ["foo", "bar", "baz"]
>>> list(map(lambda w: w.upper(), words))
['FOO', 'BAR', 'BAZ']
map takes a function as its first argument and applies it to each item of the iterable passed as its second argument. In the two examples, I pass in two different functions: one that doubles the argument that I use with the list of ints and one that turns its argument to uppercase, which I use with the list of strings.
Reply
#5
I'm not quite sure what you are after but maybe your better of with a class ?
class External:
    def __init__(self, a, b, lval, hval, yr):
        G, E = [], []
        for i in range(len(a)):
            G.append(0 if min(b[i], hval) < max(a[i], lval)
                     else min(b[i], hval) - max(a[i], lval))
        for i in range(len(a)):
            E.append(b[i] - a[i] - G[i])

        self.E = E
        self.yr = yr

    @property
    def ratio(self):
        return max(self.E[:-self.yr])

    @property
    def index(self):
        return self.E.index(self.ratio)


L = [1.238623532, 1.315924461, 1.430787909, 0.65436604, 0.78646411, 1.551692625,
     1.143410924, 1.044302349, 1.12971696, 1.007285185, 1.009553518, 0.646888596,
     1.027950548, 0.950471257, 1.048221271, 1.070840989]
H = [1.514019069, 1.662165686, 3.098538659, 3.148539828, 2.248779234, 2.542734245,
     2.312232392, 1.855592543, 1.99976568, 1.715706499, 2.111987812, 1.74066515,
     2.038750404, 2.058942087, 2.0941254, 1.498883955]

external = External(L, H, 1.00955235351066, 2.03874956866074, 6)
print(external.ratio, external.index)
Output:
1.4649765728499204 3
Reply
#6
(Aug-09-2020, 05:13 PM)ndc85430 Wrote: map takes a function as its first argument and applies it to each item of the iterable passed as its second argument. In the two examples, I pass in two different functions: one that doubles the argument that I use with the list of ints and one that turns its argument to uppercase, which I use with the list of strings.

Thanks, it's useful to recall this as I will do a lot of list calculation. I'll see how that can simplify my clumsy codes but currently it would be great if I have a way to define multiple functions within the same def process.

(Aug-09-2020, 05:18 PM)Yoriz Wrote: I'm not quite sure what you are after but maybe your better of with a class ?

Seems to be more like a programmer's work but I would still need to assign something to an output each time before getting the ratio and index. I will use the function a lot so it would add up the work. Besides that also means I cannot maintain the structure of line 5 of a higher function I showed earlier, since the ratio still cannot be just called up as a function.

def maxexternalratio(a, b, yr):
    Etemp = []
    for i in range(len(a)):
        for j in range(len(a)):
             Etemp.append(external(a, b, a[i], b[j], yr)['ratio'])
    return max(Etemp)
If so I think I'd rather define two functions separately with nearly identical codes although that would be clumsy and obviously amateur.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Defining Functions theturtleking 4 2,733 Dec-07-2021, 06:45 PM
Last Post: deanhystad
  Run multiple process using subprocess Shiri 3 3,733 Nov-28-2021, 10:58 AM
Last Post: ghoul
  Process multiple pdf files Spartan314 1 1,297 Oct-27-2021, 10:46 PM
Last Post: Larz60+
  How to call multiple functions sequentially Mayo 2 9,161 Jan-06-2021, 07:37 PM
Last Post: Mayo
Question trouble with functions "def", calling/defining them Duck_Boom 13 4,234 Oct-21-2020, 03:50 AM
Last Post: Duck_Boom
  Multiple lambda functions in zipped list not executing psolar 0 1,570 Feb-13-2020, 12:53 PM
Last Post: psolar
  naming images adding to number within multiple functions Bmart6969 0 1,894 Oct-09-2019, 10:11 PM
Last Post: Bmart6969
  How to sharing object between multiple process from main process using Pipe Subrata 1 3,619 Sep-03-2019, 09:49 PM
Last Post: woooee
  Defining functions TommyAutomagically 1 1,842 Apr-25-2019, 06:33 PM
Last Post: Yoriz
  Multiple process access to a serial port mkonnov 0 3,018 Apr-14-2019, 12:42 PM
Last Post: mkonnov

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020