Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way of generating data outside of a method

Tags:

python

A silly question, but this is bugging me (regardless of downvotes for my imbecility!): I think I have picked up a nonsensical fear of generating data outside of a method that method uses (without changing), but I am unsure if this is the case.

Let's say I have a method myfx, that will need some dictionary datadex that requires a lengthy operation to make, but will be common to all the calls during that session. The simplest, but not doable, way is:

def myfx(x,foo):
    datadex={f:42 for f in foo} #initialise
    mungeddata=datadex[x]+1  #munge
    return mungeddata

but that will waste too much time. So the best thing would be to make it in the main scope once as one does with class variables:

datadex={f:42 for f in foo} #initialise
def myfx(x):
    mungeddata=datadex[x]+1  #munge
    return mungeddata

However, I do not know why, but I go to great lengths to avoid this. It is inelegant, but I don't think that is the case. I generally resort to closures:

def initialise(foo):
    datadex={f:42 for f in foo} #initialise
    def myfx(x):
        mungeddata=datadex[x]+1  #munge
        return mungeddata
    return myfx

Or worse making a class. I code nearly exclusively in Python and JS. My best guess is it is a throwback from my Perl coding days —Subconsciously I somethinge find myself writing variables first alla Pascal, so I think some habits linger as shadows—, but that would not explain the class or closure way as OO-Perl is completely different.

like image 244
Matteo Ferla Avatar asked Feb 09 '16 19:02

Matteo Ferla


2 Answers

A class is the right way to encapsulate this behavior. You have some data that is shared by multiple function calls.

class MungedData(object):

    def __init__(self, foo):
        self.datadex = {f:42 for f in foo}

    def myfx(self, x):
        return self.datadex[x] + 1

md = MungedData(somefoo)
print(md.myfx(arg1))
print(md.myfx(arg2))

While there are certainly other alternatives, this is going to be the most common and straightforward method in Python.

like image 120
chepner Avatar answered Nov 01 '22 13:11

chepner


Python functions are objects and can have attributes, if you don't want to have your function inside a class you can do something like this:

def myfx(x):
    mungeddata=myfx.datadex[x]+1  #munge
    return mungeddata
myfx.datadex={f:42 for f in foo} #initialise

I guess that what you are trying to avoid is having a global variable.

like image 39
imreal Avatar answered Nov 01 '22 13:11

imreal