alukach
alukach

Reputation: 6298

Python: Efficient way to put multiple variables through a function

I have a bunch of variables that are equal to values pulled from a database. Sometimes, the database doesn't have a value and returns "NoneType". I'm taking these variables and using them to build an XML file. When the variable is NoneType, it causes the XML value to read "None" rather than blank as I'd prefer.

My question is: Is there an efficient way to go through all the variables at once and search for a NoneType and, if found, turn it to a blank string?

ex.

from types import *

[Connection to database omitted]

color = database.color
size = database.size
shape = database.shape
name = database.name
... etc

I could obviously do something like this:

if type(color) is NoneType:
  color = ""

but that would become tedious for the 15+ variables I have. Is there a more efficient way to go through and check each variable for it's type and then correct it, if necessary? Something like creating a function to do the check/correction and having an automated way of passing each variable through that function?

Upvotes: 0

Views: 931

Answers (4)

Boaz Yaniv
Boaz Yaniv

Reputation: 6424

All the solutions given here will make your code shorter and less tedious, but if you really have a lot of variables I think you will appreciate this, since it won't make you add even a single extra character of code for each variable:

class NoneWrapper(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        value = getattr(self.wrapped, name)
        if value is None:
            return ''
        else:
            return value

mydb = NoneWrapper(database)
color = mydb.color
size = mydb.size
shape = mydb.shape
name = mydb.name

# All of these will be set to an empty string if their
# original value in the database is none

Edit

I thought it was obvious, but I keep forgetting it takes time until all the fun Python magickery becomes a second nature. :) So how NoneWrapper does its magic? It's very simple, really. Each python class can define some "special" methods names that are easy to identify, because they are always surrounded by two underscores from each side. The most common and well-known of these methods is __init__(), which initializes each instance of the class, but there are many other useful special methods, and one of them is __getattr__(). This method is called whenever someone tries to access an attribute. of an instance of your class, and you can customize it to customize attribute access.

What NoneWrapper does is to override getattr, so whenever someone tries to read an attribute of mydb (which is a NoneWrapper instance), it reads the attribute with the specified name from the wrapped object (in this case, database) and return it - unless it's value is None, in which case it returns an empty string.

I should add here that both object variables and methods are attributes, and, in fact, for Python they are essentially the same thing: all attributes are variables that could be changed, and methods just happen to be variables that have their value set to a function of special type (bound method). So you can also use getattr() to control access to functions, which could lead to many interesting uses.

Upvotes: 3

Ruggero Turra
Ruggero Turra

Reputation: 17730

you can simply use:

color = database.color or ""

another way is to use a function:

def filter_None(var):
    "" if (a is None) else a

color = filter_None(database.color)

I don't know how the database object is structured but another solution is to modify the database object like:

def myget(self, varname):
   value = self.__dict__[varname]
   return "" if (value is None) else value

DataBase.myget = myget
database = DataBase(...)
[...]
color = database.myget("color")

you can do better using descriptors or properties

Upvotes: 0

MRAB
MRAB

Reputation: 20664

If you're already getting them one at a time, it's not that much longer to write:

def none_to_blank(value):
    if value is None:
        return ""
    return value

color = none_to_blank(database.color)
size = none_to_blank(database.size)
shape = none_to_blank(database.shape)
name = none_to_blank(database.name)

Incidentally, use of "import *" is generally discouraged. Import only what you're using.

Upvotes: 0

user574435
user574435

Reputation: 143

The way I would do it, although I don't know if it is the best, would be to put the variables you want to check and then use a for statement to iterate through the list.

check_vars = [color,size,shape,name]
for var in check_vars:
    if type(var) is NoneType:
        var = ""

To add variables all you have to do is add them to the list.

Upvotes: 0

Related Questions