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.
    • 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