String/Number Conversion

  • Thread starter Andreas Hofmann
  • Start date
A

Andreas Hofmann

Hello Folks!

I've got a little problem here, which which really creeps me out at the
moment.
I've got some strings, which only contain numbers plus eventually one
character as si-postfix (k for kilo, m for mega, g for giga). I'm trying
to convert those strings to integers, with this function:


def eliminate_postfix(value):
if type(value) is str:
value.upper()
if value.endswith('K'):
mult = 1000
elif value.endswith('M'):
mult = 1000000
elif value.endswith('G'):
mult = 1000000000
else:
mult = 1

if mult is 1:
value = string.atoi(value)
else:
value = string.atoi(value[:-1]) * mult
return value



The problem is as follows: Everytime a string with a postfix should get
converted, mult does not get set properly. It is always 1. Does anyone
have an idea how to fix this? I just don't see it, maybe because I'm
pretty new to python or because I'm just blind I would be really greatful.

Kind regards,
Andy
 
J

josh logan

Hello Folks!

I've got a little problem here, which which really creeps me out at the
moment.
I've got some strings, which only contain numbers plus eventually one
character as si-postfix (k for kilo, m for mega, g for giga). I'm trying
to convert those strings to integers, with this function:

def eliminate_postfix(value):
         if type(value) is str:
                 value.upper()
                 if value.endswith('K'):
                         mult = 1000
                 elif value.endswith('M'):
                         mult = 1000000
                 elif value.endswith('G'):
                         mult = 1000000000
                 else:
                         mult = 1

                 if mult is 1:
                         value = string.atoi(value)
                 else:
                         value = string.atoi(value[:-1]) * mult
         return value

The problem is as follows: Everytime a string with a postfix should get
converted, mult does not get set properly. It is always 1. Does anyone
have an idea how to fix this? I just don't see it, maybe because I'm
pretty new to python or because I'm just blind I would be really greatful..

Kind regards,
Andy

Hello,

1. You call value.upper(), but you do not capture the results of that
method. Strings are immutable in Python.
2. You should use == instead of "is" in the comparison of mult being
1.
 
J

John Machin

Hello Folks!

I've got a little problem here, which which really creeps me out at the
moment.
I've got some strings, which only contain numbers plus eventually one
character as si-postfix (k for kilo, m for mega, g for giga). I'm trying
to convert those strings to integers, with this function:

def eliminate_postfix(value):
if type(value) is str:

Don't use "is" unless you are really sure that "==" won't do the job.
Better idiom:
if isinstance(value, str):
value.upper()

This causes your "mult is always 1" problem. You need:
value = value.upper()
Why? Because strings are immutable. String methods like upper return a
new string, they don't change the existing string.
if value.endswith('K'):
mult = 1000
elif value.endswith('M'):
mult = 1000000
elif value.endswith('G'):
mult = 1000000000
else:
mult = 1

if mult is 1:

Lose "is". In fact, lose the whole "if" statement. See below.
value = string.atoi(value)

Don't use deprecated functions from the string module. Use the built-
in float function to convert from text.
else:
value = string.atoi(value[:-1]) * mult
return value

Those last few statements look somewhat tortuous. Try this:
else: # mult would be 1, but we don't need it
return float(value)
return float(value[:-1]) * mult

HTH,
John
 
J

John Machin

                           ^^
You're testing for identity, not for equality.
Change it to "if mult == 1". Is it alright now?

Although he definitely should not be using "is" here, that can not be
the problem if he is using CPython. As an optimisation, small integers
are interned i.e. for each small integer, there is only one object.
 
B

bearophileHUGS

Andreas Hofmann, there are several problems in your code:
if type(value) is str:

Better to use isinstance() and to compare it with basestring instead.

value.upper()

This does nothing, python strings are immutable, so they don't get
changed in-place, so you have to assign that result to some name,
possibly a different name.
I also suggest you to strip the uppered string, to remove head/tail
spaces.
Your indenting isn't much good, I suggest you to use only four spaces
for each indent (you can also use one tab, but I don't suggest this).

if value.endswith('K'):
mult = 1000
elif value.endswith('M'):
mult = 1000000
elif value.endswith('G'):
mult = 1000000000
else:
mult = 1

This is okay. You can also put those key-values in a dict, that you
can access with the get method with a default 1, but it may be
overkill.

if mult is 1:
value = string.atoi(value)
else:
value = string.atoi(value[:-1]) * mult
return value

Instead of using string.atoi, use the int() builtin.

If you follow my suggestions you will have a function that works in
many situations. It will raise exceptions in other situations, but
that's good.

But to not need much of our help in your future code I suggest you to
use the Python shell and test every line you write. I also suggest you
to start right now using tests, for example like this:

def eliminate_postfix(value):
""" Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 10: '' Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 10: '100H' 100000000
"""
... function code ...


if __name__ == "__main__":
import doctest
doctest.testmod()
print "Doctests done.\n"

That will improve your coding a LOT, reducing your bug count, etc.

Bye,
bearophile
 
A

Andreas Hofmann

Thanks a lot, I got it working now.
Thanks also to the other guys, your numerous hints were really valuable!

Kind regards,
Andy

John said:
Hello Folks!

I've got a little problem here, which which really creeps me out at the
moment.
I've got some strings, which only contain numbers plus eventually one
character as si-postfix (k for kilo, m for mega, g for giga). I'm trying
to convert those strings to integers, with this function:

def eliminate_postfix(value):
if type(value) is str:

Don't use "is" unless you are really sure that "==" won't do the job.
Better idiom:
if isinstance(value, str):
value.upper()

This causes your "mult is always 1" problem. You need:
value = value.upper()
Why? Because strings are immutable. String methods like upper return a
new string, they don't change the existing string.
if value.endswith('K'):
mult = 1000
elif value.endswith('M'):
mult = 1000000
elif value.endswith('G'):
mult = 1000000000
else:
mult = 1

if mult is 1:

Lose "is". In fact, lose the whole "if" statement. See below.
value = string.atoi(value)

Don't use deprecated functions from the string module. Use the built-
in float function to convert from text.
else:
value = string.atoi(value[:-1]) * mult
return value

Those last few statements look somewhat tortuous. Try this:
else: # mult would be 1, but we don't need it
return float(value)
return float(value[:-1]) * mult

HTH,
John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,250
Latest member
Charlesreero

Latest Threads

Top