omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    keyboard
    7
    13
    3778
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • talns100
      talns100 last edited by talns100

      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?

      bennr01 Robert_Tompkins mikael 3 Replies Last reply Reply Quote 0
      • bennr01
        bennr01 @talns100 last edited by

        @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'sraw_input()`.

        To fix this, you could:

        • run the script as py2 instead (not recommended)
        • wrap the input() in a int() (int(input("Number: ")))
        • import ast and use ast.literal_eval(input("Number: ")).

        The last variant will allow inputing any value while preventing python code execution.

        1 Reply Last reply Reply Quote 0
        • ccc
          ccc last edited by ccc

          Does anyone use Python 2 anymore?

          i = int(input("Give me a number: "))

          bennr01 1 Reply Last reply Reply Quote 0
          • bennr01
            bennr01 @ccc last edited by

            @ccc said:

            Does anyone use Python 2 anymore?

            Please don't judge those of us who prefer the version of python closer to perfection.

            1 Reply Last reply Reply Quote 1
            • Robert_Tompkins
              Robert_Tompkins @talns100 last edited by Robert_Tompkins

              @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!

              1 Reply Last reply Reply Quote 0
              • mikael
                mikael @talns100 last edited by

                @talns100, as others have pointed out, int is a quick way to get the number. Always a good idea to wrap it in try ... 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 input 1.0, for example.

                1 Reply Last reply Reply Quote 1
                • cvp
                  cvp last edited by cvp

                  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)
                  

                  1 Reply Last reply Reply Quote 0
                  • Robert_Tompkins
                    Robert_Tompkins last edited by Robert_Tompkins

                    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.

                    1 Reply Last reply Reply Quote 0
                    • ccc
                      ccc last edited by

                      str.lower() is your friend…

                      invalid_names = ("admin", "sudo")
                      
                              if self.player_name.lower() in invalid_names:
                                  # Debug handling is done here
                      
                      Robert_Tompkins 1 Reply Last reply Reply Quote 0
                      • Robert_Tompkins
                        Robert_Tompkins @ccc last edited by

                        @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() 
                        
                        cvp 1 Reply Last reply Reply Quote 0
                        • cvp
                          cvp @Robert_Tompkins last edited by

                          @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()
                          
                          1 Reply Last reply Reply Quote 0
                          • JonB
                            JonB last edited by

                            For doing 1:1 character replacements, maketrans plus translate 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.

                            bennr01 1 Reply Last reply Reply Quote 1
                            • bennr01
                              bennr01 @JonB last edited by

                              @JonB said:

                              For doing 1:1 character replacements, maketrans plus translate 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.

                              1 Reply Last reply Reply Quote 1
                              • First post
                                Last post
                              Powered by NodeBB Forums | Contributors