Differentiating Python variables as str or int - python

I have a file that has 3 values on each line. It is a fairly random file, and any of these values can be str or int.
George, 34s, Nikon
42, absent, Alan
apple, 111, 41
marked, 15, never
...
So, I read in the line, and using split I get the first value:
theFile = r"C:\... "
tDC = open(theFile, "r")
for theLine in tDC:
a, b, c = theLine.split(',')
So far so good.
Where I'm stuck is when I try to deal with variable a. I need to deal with it differently if it is a str or if it is an int. I tried setting a = int(a), but if it is a string (e.g., 'George') then I get an error. I tried if type(a) = int or if isinstance(a,int), but neither work because all the values come in as a string!
So, how do I evaluate the value NOT looking at its assigned 'type'? Specifically, I want to read all the a's and find the maximum value of all the numbers (they'll be integers, but could be large -- six digits, perhaps).
Is there a way to read in the line so that numbers come in as numbers and strings come in as strings, or perhaps there is a way to evaluate the value itself without looking at the type?

The first point is that you need some rule that tells you which values are integers and which ones aren't. In a data set that includes things like 32s, I'm not sure it makes sense to just treat anything that could be an integer as if it were.
But, for simplicity, let's assume that is the rule you want: anything that could be an integer is. So, int(a) is already pretty close; the only issue is that it can fail. What do you do with that?
Python is designed around EAFP: it's Easier to Ask Forgiveness than Permission. Try something, and then deal with the fact that it might fail. As Cyber suggests, with a try statement:
try:
intvalue = int(a)
except ValueError:
# Oops, it wasn't an int, and that's fine
pass
else:
# It was an int, and now we have the int value
maxvalue = max(maxvalue, intvalue)

isalpha() Returns "True" if all characters in the string are in the alphabet
isnumeric() Returns "True" if all characters in the string are numeric
so;
data="Hello World"
print(data.isnumeric()) #it will retuns with False
print(data.isalpha()) # True
Sorry for my soulles answer, I just came here for same issue, I found a different way and wanted to share with you

values = theLine.split(',')
for value in values:
try:
number = int(value)
# process as number
except ValueError:
# process value as string

this :
def ret_var(my_var: int) -> int:
try:
intvalue = int(my_var)
return my_var
except ValueError:
print("my_var not int!")

Related

I want to distinguish between true digit and a string digit

I want to check a 'x' string whether it is a digit or not in advance.
'1' is naturally a digit.
But and I will use ① what is calld a string number very much.
I don't know the range of string numbers IDE judges as a digit.
'①'.isdigit() returns True.
'⑴'.isdigit() returns True.
'ⅰ' or 'Ⅰ' returns False.
'㈠' returns False. (kanji version of (1) )
'❶' returns True.
I want to do like this.
for s in data:
if s.isdigit():
int_ = int(s)
If I accept '①', int will throw an error. Now, I write try:except for it.
Because I'm a japanese, I often use '①' or '⑴'
How to distinguish isdigit or not isdigit in advance?
Should I rely on try:except or counting all of them in advance?
regular expression?
The main problem is I don't know what is judged as a digit.
data = ["1", "23", "345", "①", "(1)", "(2)"]
This data is dynamic value. It will be changed every time.
Moreover, the string like this may expand in the future.
I hope the string of isdigit() == True is accepted by int().
I don't have an urgent problem because of try: except.
I believe that the str.isdecimal method fits your requirements. It excludes strings like '①', but includes other strings like '١' which are accepted by int.
>>> int('١')
1

Keep zero digit save while converting string to integer in python

I am converting a string into integer using int function and it is working fine but i want to keep save zero digit that are at the start of the string.
string_value = '0123'
print(int(string_value))
result is 123
How can i format output 0123 as in integer type value not in string.
You can't, but if you want to put 0's (zero padding) at the beginning of your number, this is the way to do it.
"{:04}".format(123)
# '0123'
"{:05}".format(123)
# '00123'
Like every one said you can try above answers or the following :
string_value = '0123'
int_no = int(string_value)
print("%04d" % int_no)
print(string_value.zfill(4))
Both will give same answer
Impossible, you cannot get an integer value of 0123.
You should change your mind, you do not actually need 0123 in integer, but you need to keep zero when displaying it. So the question should change to how to format output.

Python 3 taking multiple data types in input, separated by space

So i need to find a way to take multiple data types as an input and store them in variables. Lets say i have 3 variables, each of them should store a fixed data type
a - float
b - str
c - int
and if the user enters a wrong, he will be asked to type again.
The user will enter all of them, separated by space but i can't think of a way to store them in the variables, while keeping the data type. I've tried with .split(), but it just transforms them into strings. It's probably something quite obvious, but can't figure it out right now. Thanks in advance!
Maybe:
def myfucn(vars):
vars = vars.split()
try:
float(vars[0])
if not "." in vars[0]:
raise Exception("First var should be INT not Float")
except ValueError:
print("Error not Float found")
try:
int(vars[2])
except ValueError:
print("Error Int no found")
#answer
a_float, b_str, c_int = vars
print(" Yes ")
greetings
You are on the right track if the split() function. The problem is that when you say that user will give three values separated by ' ', you are taking in a string.
The following is a string:
'34.44 35.45 5'
Maybe what you can do is after using split, you can cast each returned item to a variable. If you still need to check the type of variable, you can use the type() function.
Hope this helps!

Find the most restrictive data type to which a string can be cast (Python)

I want to read text files such as CSV, or tab-separated values, but only columns which can be cast to numbers. For instance, if a column contains only strings, I'd like not to read it. This is because I'd like to avoid working with numpy arrays of multiple data types (I would be interested to know why I should, however questions should not be subject to discussion).
Various questions were quite close to mine (see 1, 2 and 3). However, apart from 1, they focus on converting the string rather than check which data type it could be converted to, which is why I mostly followed 1 to obtain the desired result.
Numpy's genfromtxt already does something close (by using the "dtype" argument). I suppose I could use this (with "dtype" set to None), and then just checking each column's data type.
Here's what I have so far:
def data_type(string_to_test):
"""
Checks to which data type a string can be cast. The main goal is to convert strings to floats.
The hierarchy for upcasting goes like this: int->float->complex->string. Thus, int is the most restrictive.
:param string_to_test: A string of character that hypothetically represents a number
:return: The most restrictive data type to which the string could be cast.
"""
# Do this to convert also floats that use coma instead of dots:
string_to_test = string_to_test.replace(',', '.')
# First, try to switch from string to int:
try:
# This will yield True if string_to_test represents an int, or a float that is equal to an int (e.g.: '1.0').
if int(float(string_to_test)) == float(string_to_test):
return int
else:
int(string_to_test)
return float
except ValueError:
# If it doesn't work, try switching from string to float:
try:
float(string_to_test)
return float
except ValueError:
# Happens with complex numbers and types (e.g.: float(4 + 3j), or float(float64)).
# If this still doesn't work, try switching from string to complex:
try:
# Make sure spaces between operators don't cause any problems (e.g.: '1 + 4j' will not work,
# while '1+4j' will).
complex(string_to_test.replace(' ', ''))
return complex
# If none of the above worked, the string is said not to represent any other data types (remember this
# function is supposed to be used on data that is read from files, so checking only for those types should
# be exhaustive enough).
except ValueError:
return str
My biggest problem with this is that I find it rather ugly, and also that There could be cases I haven't thought about. Thus my question is "could it be done in a better way?".
Also, I'm interested to know when would it be better to return strings representing that data type, instead of the class itself (e.g.: return 'complex' as a string instead of complex, the class). For instance, I know I can use both (the string or the class) when using the method astype for numpy arrays.
Thanks in advance!
Same logic, less-"ugly" presentation:
def data_type(string_to_test, types=(int,float,complex)):
string_to_test = string_to_test.replace(' ', '')
for typ in types:
try: value = typ(string_to_test)
except ValueError: pass
else: break
else: typ = str
# special cases:
if typ is float and int in types and value == int(value): typ = int
if typ is int and bool in types and value == bool(value): typ = bool
return typ
This also lends itself being extended a little more easily in that you can pass a different hierarchy of types—note that, analogous to your rule for "boiling down" a float into an int, I've included a rule for further boiling down an int into a bool if bool is one of the desired types (by default it isn't, since you don't specify it in the question, but it could be).
I would keep the resulting type object on the principle of not throwing away information when you don't need to (you can always access its .__name__ if you want a string).

Float converted to 2.dp reverts to original number of decimal places when inserted into a string

I have created the following snippet of code and I am trying to convert my 5 dp DNumber to a 2 dp one and insert this into a string. However which ever method I try to use, always seems to revert the DNumber back to the original number of decimal places (5)
Code snippet below:
if key == (1, 1):
DNumber = '{r[csvnum]}'.format(r=row)
# returns 7.65321
DNumber = """%.2f""" % (float(DNumber))
# returns 7.65
Check2 = False
if DNumber:
if DNumber <= float(8):
Check2 = True
if Check2:
print DNumber
# returns 7.65
string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str("""%.2f""" % (float(gtpe))))
# returns: test Hello 7.65321 test
string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str(DNumber))
# returns: test Hello 7.65321 test
What I hoped it would return: test Hello 7.65 test
Any Ideas or suggestion on alternative methods to try?
It seems like you were hoping that converting the float to a 2-decimal-place string and then back to a float would give you a 2-decimal-place float.
The first problem is that your code doesn't actually do that anywhere. If you'd done that, you would get something very close to 7.65, not 7.65321.
But the bigger problem is that what you're trying to do doesn't make any sense. A float always has 53 binary digits, no matter what. If you round it to two decimal digits (no matter how you do it, including by converting to string and back), what you actually get is a float rounded to two decimal digits and then rounded to 53 binary digits. The closest float to 7.65 is not exactly 7.65, but 7.650000000000000355271368.* So, that's what you'd end up with. And there's no way around that; it's inherent to the way float is stored.
However, there is a different type you can use for this: decimal.Decimal. For example:
>>> f = 7.65321
>>> s = '%.2f' % f
>>> d = decimal.Decimal(s)
>>> f, s, d
(7.65321, '7.65', Decimal('7.65'))
Or, of course, you could just pass around a string instead of a float (as you're accidentally doing in your code already), or you could remember to use the .2f format every time you want to output it.
As a side note, since your DNumber ends up as a string, this line is not doing anything useful:
if DNumber <= 8:
In Python 2.x, comparing two values of different types gives you a consistent but arbitrary and meaningless answer. With CPython 2.x, it will always be False.** In a different Python 2.x implementation, it might be different. In Python 3.x, it raises a TypeError.
And changing it to this doesn't help in any way:
if DNumber <= float(8):
Now, instead of comparing a str to an int, you're comparing a str to a float. This is exactly as meaningless, and follows the exact same rules. (Also, float(8) means the same thing as 8.0, but less readable and potentially slower.)
For that matter, this:
if DNumber:
… is always going to be true. For a number, if foo checks whether it's non-zero. That's a bad idea for float values (you should check whether it's within some absolute or relative error range of 0). But again, you don't have a float value; you have a str. And for strings, if foo checks whether the string is non-empty. So, even if you started off with 0, your string "0.00" is going to be true.
* I'm assuming here that you're using CPython, on a platform that uses IEEE-754 double for its C double type, and that all those extra conversions back and forth between string and float aren't introducing any additional errors.
** The rule is, slightly simplified: If you compare two numbers, they're converted to a type that can hold them both; otherwise, if either value is None it's smaller; otherwise, if either value is a number, it's smaller; otherwise, whichever one's type has an alphabetically earlier name is smaller.
I think you're trying to do the following - combine the formatting with the getter:
>>> a = 123.456789
>>> row = {'csvnum': a}
>>> print 'test {r[csvnum]:.2f} hello'.format(r=row)
test 123.46 hello
If your number is a 7 followed by five digits, you might want to try:
print "%r" % float(str(x)[:4])
where x is the float in question.
Example:
>>>x = 1.11111
>>>print "%r" % float(str(x)[:4])
>>>1.11

Categories

Resources