Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Numbers behave like strings in iPhone
-
Hey, when I execute a script and enters a number as input it automatically behaves as a string.
How to fix that? I can’t add inputs cuase of it.
Will casting fix the problem?
Why does it happen in the first place? -
@talns100 If I understand your problem correctly, you call
input("Number: ")
and get a string value as a return value although you had expected a string.This is a python2 vs python3 issue. In python2,
raw_input()
returned a string while ’input()evaluated the input as a python object. In py3,
input()is equivalent to python2's
raw_input()`.To fix this, you could:
- run the script as py2 instead (not recommended)
- wrap the
input()
in aint()
(int(input("Number: "))
) import ast
and useast.literal_eval(input("Number: "))
.
The last variant will allow inputing any value while preventing python code execution.
-
Does anyone use Python 2 anymore?
i = int(input("Give me a number: "))
-
@ccc said:
Does anyone use Python 2 anymore?
Please don't judge those of us who prefer the version of python closer to perfection.
-
@talns100 said:
Hey, when I execute a script and enters a number as input it automatically behaves as a string.
How to fix that? I can’t add inputs cuase of it.
Will casting fix the problem?
Why does it happen in the first place?Yes, user input is treated as a string by default but casting does fix the problem.
Since user input can be of any type, handling it as a string is the safest way to store the value.You can easily cast it in-line
userInput = int(input(“Enter an integer:\n”))
Or later
userInput = input(“Enter stuff:\n”) integerInput = int(userInput) floatInput = float(userInput)
That’s my two cents!
-
@talns100, as others have pointed out,
int
is a quick way to get the number. Always a good idea to wrap it intry ... except ValueError
though, to either set a default or give the user some guidance on what you expected to receive.Usually, if all I want is an int, I prefer to use
int(round(float(input())))
, just to be that little bit more tolerant of users who input1.0
, for example. -
This is my solution, using my SetTextFieldPad module.
from SetTextFieldPad import SetTextFieldPad import ui pad_integer = [{'key':'1'},{'key':'2'},{'key':'3'}, {'key':'back space','icon':'typb:Delete'}, {'key':'new row'}, {'key':'4'},{'key':'5'},{'key':'6'}, #{'key':'delete','icon':'emj:Multiplication_X'}, {'key':'new row'}, {'key':'7'},{'key':'8'},{'key':'9'}, {'key':'new row'}, {'key':'nul'},{'key':'0'},{'key':'nul'},{'key':'⏎','SFicon':'return'}] class myIntegerInput(ui.View): def __init__(self, *args, **kwargs): ui.View.__init__(self, *args, **kwargs) self.background_color = 'white' self.tf = ui.TextField() self.tf.frame = self.bounds self.tf.delegate = self SetTextFieldPad(self.tf, pad_integer) self.add_subview(self.tf) def textfield_did_end_editing(self, textfield): self.close() def intInput(prompt=''): tfv = myIntegerInput(frame=(0,0,200,50)) tfv.name = prompt tfv.present('sheet', hide_title_bar=not prompt) tfv.tf.begin_editing() tfv.wait_modal() return int('0'+tfv.tf.text) i = intInput()#'Prompt') print(i)
-
So I went through like 20 of my programs for a good, simple example..
But I realized that I don’t convert any user input in-line. I prefer to do it after storing the input to a variable.
This allows me to do my own tests on it before falling through to a default error message.For example, in my game, prompting for a name to be used for profile loading/saving..
def loadProfile(self, passedPlayerName=None, resetProfile=None): global profileLoaded listOfDebugNames = ["admin", "ADMIN", "Admin", "sudo", "SUDO", "Sudo"] if passedPlayerName != None: self.playerName = passedPlayerName else: self.playerName = console.input_alert( f'Please enter your Profile Name', 'Case Sensitive, probably', hide_cancel_button=True) if self.playerName == "": self.playerName = "NOOB" if self.playerName in listOfDebugNames: # Debug handling is done here
So with string being default, you can first check if it is equal to a debug string you specify.
Or, you can check the type of it first and handle it case by case / type by type.
Here’s a random example of me handling two cases where the item passed to a function can be a string, or can be a list of strings.def getPriceEsoItem(item): global dictOfItemFields global dictOfSearches device = zxtouch("127.0.0.1") dictOfSearches = {} argumentType = type(item) if argumentType == list: for string in item: length = len(string) dictOfSearches[string] = length else: length = len(item) dictOfSearches[item] = length
Maybe there’s a downside that I am missing.. But to me, it seems to always be better to store user input first. Then do your own handling for various input types depending on your use-case.
-
str.lower()
is your friend…invalid_names = ("admin", "sudo") if self.player_name.lower() in invalid_names: # Debug handling is done here
-
@ccc
Thanks! Yea... I just recently started using that lol. This is why I try writing programs for a wide range of things. Otherwise I don’t learn about these things!Not trying to hijack.. but how can I simplify this? Goal of this was to just strip anything that is not always used in my use-case. Like punctuation. I’m detecting text on-screen via OCR and extract it and attempt to find a match. But I want to be lenient lol.
textString = textString.replace('[', '') textString = textString.replace(']', '') textString = textString.replace(' ', ' ') textString = textString.replace("'", '') textString = textString.strip() textString = textString.lower()
-
@Robert_Tompkins said:
textString = textString.replace('[', '')
textString = textString.replace(']', '')
textString = textString.replace(' ', ' ')
textString = textString.replace("'", '')
textString = textString.strip()
textString = textString.lower()textString = textString.replace('[', '').replace(']', '').replace(' ', ' ').replace("'", '').strip().lower()
-
For doing 1:1 character replacements,
maketrans
plustranslate
makes for clean code. You list all the characters you are replacing in one string, all the replacements in the second, and all the characters to delete in the third argument to maketrans. -
@JonB said:
For doing 1:1 character replacements,
maketrans
plustranslate
makes for clean code. You list all the characters you are replacing in one string, all the replacements in the second, and all the characters to delete in the third argument to maketrans.Damn, I never knew about this. Now I can finally replace my
for c in (...): s = s.replace(c, "")
loops. My code may finally look acceptable.