Uys of Spades Uys of Spades - 4 months ago 10
Python Question

Grouping Functions by Using Classes in Python

I have been a Python Scientific Programmer for a few years now, and I find myself coming to a sort specific problem as my programs get larger and larger. I am self taught so I have never had any formal training and spent any time really on 'conventions' of coding in Python "properly".

Anyways, to the point, I find myself always creating a utils.py file that I store all my defined functions in that my programs use. I then find myself grouping these functions into their respective purposes. One way of I know of grouping things is of course using Classes, but I am unsure as to whether my strategy goes against what classes should actually be used for.

Say I have a bunch of functions that do roughly the same thing like this:

def add(a,b):
return a + b

def sub(a,b):
return a -b

def cap(string):
return string.title()

def lower(string):
return string.lower()


Now obviously these 4 functions can be seen as doing two seperate purposes one is calculation and the other is formatting. This is what logic tells me to do, but I have to work around it since I don't want to initialise a variable that corresponds to the class evertime.

class calc_funcs(object):

def __init__(self):
pass

@staticmethod
def add(a,b):
return a + b

@staticmethod
def sub(a, b):
return a - b

class format_funcs(object):
def __init__(self):
pass

@staticmethod
def cap(string):
return string.title()

@staticmethod
def lower(string):
return string.lower()


This way I have now 'grouped' these methods together into a nice package that makes finding desired methods much faster based on their role in the program.

print calc_funcs.add(1,2)
print format_funcs.lower("Hello Bob")


However that being said, I feel this is a very 'unpython-y' way to do things, and it just feels messy. Am I going about thinking this the right way or is there an alternate method?

Thank you!

Answer

Another approach is to make a util package and split up your functions into different modules within that package. The basics of packages: make a directory (whose name will be the package name) and put a special file in it, the __init__.py file. This can contain code, but for the basic package organization, it can be an empty file.

my_package/
  __init__.py
  module1.py/
  modle2.py/
  ...
  module3.py

So say you are in your working directory:

mkdir util
touch util/__init__.py

Then inside your util directory, make calc_funcs.py

def add(a,b):
    return a + b

def sub(a,b):
    return a -b

And format_funcs.py:

def cap(string):
    return string.title()

def lower(string):
    return string.lower()

And now, from your working directory, you can do things like the following:

>>> from util import calc_funcs
>>> calc_funcs.add(1,3)
4
>>> from util.format_funcs import cap
>>> cap("the quick brown fox jumped over the lazy dog")
'The Quick Brown Fox Jumped Over The Lazy Dog'

Edited to add

Notice, though, if we restart the interpreter session:

>>> import util
>>> util.format_funcs.cap("i should've been a book")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'util' has no attribute 'format_funcs'

This is what the __init__.py is for!

In __init__.py, add the following:

import util.calc_funcs, util.format_funcs

Now, restart the interpreter again:

>>> import util
>>> util.calc_funcs.add('1','2')
'12'
>>> util.format_funcs.lower("I DON'T KNOW WHAT I'M YELLING ABOUT")
"i don't know what i'm yelling about"

Yay! We have flexible control over our namespaces with easy importing! Basically, the __init__.py plays an analogous role to the __init__ method in a class definition.