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.


    If statement syntax error

    Pythonista
    7
    53
    11311
    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.
    • OkieWolf
      OkieWolf @ccc last edited by OkieWolf

      @ccc
      Could you please explain how this works in more detail?
      I realize you’ve renamed textfields but I’m not exactly understanding how the code is working. I’m mainly not understanding what’s happening with the or 0 and then the if len([x for x in (hypotenuse, short, long) if x]) != 2

      hypotenuse = float(v['hypotenuse'].text or 0)
          short = float(v['short'].text or 0)
          long = float(v['long'].text or 0)
          if len([x for x in (hypotenuse, short, long) if x]) != 2: ```
      mcriley821 1 Reply Last reply Reply Quote 0
      • mcriley821
        mcriley821 @OkieWolf last edited by ccc

        @OkieWolf

        hypotenuse = float(v['hypotenuse'].text or 0)
            short = float(v['short'].text or 0)
            long = float(v['long'].text or 0)
            if len([x for x in (hypotenuse, short, long) if x]) != 2: ```
        

        v['short'].text or 0 will choose 0 if the text is "". You won’t hit an exception for a blank textfield. You will get an error if the text is alphabetical though.

        (hypotenuse,short,long) is a tuple and [x for x in (hypotenuse,short,long) if x] is a list comprehension that steps through the tuple
        and makes a list of the values that exist. Then if the length of that list isn’t 2, then you don’t have a correct input

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

          I need to probably rewrite the whole program because I’ve added more error trapping and a fourth textfield. It has increased complexity quite a bit, at least for me. It now cycles through all four textfields, find any two valid fields, decides whether to use Pythagorean Theorem or plain trig, and checks all for errors. One error in particular is that it is possible with the answers to have the short side of the triangle be longer than the long side. Obviously this can never happen so it’s now trapped and alerts the user.
          Below is what I now have. I realize my code is a longer than it needs to be and fairly cumbersome at this point but I’m just learning Python and intend to try to rewrite it in a better and more efficient way.

          def button3_tapped(sender):
          	if (v['textfield3'].text)!="" and (v['textfield4'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		hyp = float(v['textfield3'].text)
          		sht = float(v['textfield4'].text)
          		hypa = hyp
          		shta = sht
          		hyp = pow(hyp,2)
          		sht = pow(sht,2)
          		lng = math.sqrt(hyp - sht)
          		lnga = lng
          		ang = math.asin(shta/hypa)
          		ang = math.degrees(ang)
          		v['textfield5'].text_color = 'green'
          		v['textfield5'].text = str(lng)
          		v['textfield6'].text_color = 'green'
          		v['textfield6'].text = str(ang)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	elif (v['textfield4'].text)!="" and (v['textfield5'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		sht = float(v['textfield4'].text)
          		shta = sht
          		lng = float(v['textfield5'].text)
          		lnga = lng
          		sht = pow(sht,2)
          		lng = pow(lng,2)
          		hyp = math.sqrt(sht + lng)
          		hypa = hyp
          		ang = math.asin(shta/hypa)
          		ang = math.degrees(ang)
          		v['textfield3'].text_color = 'green'
          		v['textfield3'].text = str(hyp)
          		v['textfield6'].text_color = 'green'
          		v['textfield6'].text = str(ang)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	elif (v['textfield3'].text)!="" and (v['textfield5'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		hyp = float(v['textfield3'].text)
          		hypa = hyp
          		lng = float(v['textfield5'].text)
          		lnga = lng
          		hyp = pow(hyp,2)
          		lng = pow(lng,2)
          		sht = math.sqrt(hyp - lng)
          		shta = sht
          		ang = math.asin(shta/hypa)
          		ang = math.degrees(ang)
          		v['textfield4'].text_color = 'green'
          		v['textfield4'].text = str(sht)
          		v['textfield6'].text_color = 'green'
          		v['textfield6'].text = str(ang)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	elif (v['textfield3'].text)!="" and (v['textfield6'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		hyp = float(v['textfield3'].text)
          		ang = float(v['textfield6'].text)
          		ang = math.radians(ang)
          		hypa = hyp
          		sht = hyp * math.sin(ang)
          		shta = sht
          		hypc = pow(hyp,2)
          		shtc = pow(sht,2)
          		lng = math.sqrt(hypc - shtc)
          		lnga = lng
          		v['textfield5'].text_color = 'green'
          		v['textfield5'].text = str(lng)
          		v['textfield4'].text_color = 'green'
          		v['textfield4'].text = str(sht)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	elif (v['textfield4'].text)!="" and (v['textfield6'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		sht = float(v['textfield4'].text)
          		ang = float(v['textfield6'].text)
          		ang = math.radians(ang)
          		shta = sht
          		hyp = sht / math.sin(ang)
          		hypa = hyp
          		hypc = pow(hyp,2)
          		shtc = pow(sht,2)
          		lng = math.sqrt(hypc - shtc)
          		shta = sht
          		v['textfield5'].text_color = 'green'
          		v['textfield5'].text = str(lng)
          		v['textfield3'].text_color = 'green'
          		v['textfield3'].text = str(hyp)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	elif (v['textfield5'].text)!="" and (v['textfield6'].text)!="":
          		v['label7'].background_color = 'white'
          		v['label7'].text_color = 'white'
          		v['label7'].text = ''
          		lng = float(v['textfield5'].text)
          		ang = float(v['textfield6'].text)
          		ang = math.radians(ang)
          		lnga = lng
          		hyp = lng / math.cos(ang)
          		hypa = hyp
          		hypc = pow(hyp,2)
          		lngc = pow(lng,2)
          		sht = math.sqrt(hypc - lngc)
          		shta = sht
          		v['textfield4'].text_color = 'green'
          		v['textfield4'].text = str(sht)
          		v['textfield3'].text_color = 'green'
          		v['textfield3'].text = str(hyp)
          		shtb = float(v['textfield4'].text)
          		lngb = float(v['textfield5'].text)
          		if shtb > lngb:
          			v['label7'].background_color = 'red'
          			v['label7'].text_color = 'white'
          			v['label7'].text = 'ERROR. Short side cannot be longer than long side.'
          	else:
          		v['label7'].background_color = 'red'
          		v['label7'].text_color = 'white'
          		v['label7'].text = 'ERROR' ```
          1 Reply Last reply Reply Quote 0
          • OkieWolf
            OkieWolf last edited by

            If you import math why do you still have to say math.sqrt and math.cos?
            But then other things like pow don’t have to say math.pow.

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

              pow() is a Python builtin. https://docs.python.org/3/library/functions.html

              You can also say from math import cos, sin, tan to use the single word functions.

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

                This post is deleted!
                1 Reply Last reply Reply Quote 0
                • OkieWolf
                  OkieWolf @ccc last edited by OkieWolf

                  @ccc

                  I’m attempting to rewrite my code to be more efficient and am utilizing a couple of code snippets that a couple of you have supplied. However, in the below code I noticed that the output is 0.0 if both inputs happen to be the same number. I’m not understanding why.

                  def button3_tapped(sender):
                  	hypotenuse = float(v['hypotenuse'].text or 0)
                  	short = float(v['short'].text or 0)
                  	long = float(v['long'].text or 0)
                  	if len([x for x in (hypotenuse, short, long) if x]) != 2:
                  		v['mess'].text = "Enter two fields"
                  		v['mess'].background_color = 'red'
                  		v['mess'].text_color = 'white'
                  		return
                  	if hypotenuse:
                  		if short and not long:
                  			v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2))
                  			v['long'].text_color = 'green'
                  		elif long and not short:
                  			v['short'].text = str(math.sqrt(hypotenuse ** 2 - long ** 2))
                  			v['short'].text_color = 'green'
                  	else:
                  		v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2))
                  		v['hypotenuse'].text_color = 'green' ```
                  1 Reply Last reply Reply Quote 0
                  • ccc
                    ccc last edited by ccc

                    if both inputs happen to be the same number

                    if hypotenuse:
                        if short:
                            The rules of math say that the hypotenuse must be greater than short.
                        else
                            The rules of math say that the hypotenuse must be greater than long.
                    else:
                        short could be the same number as long  # <-- this is the only instance where both inputs could be the same number
                    
                    if hypotenuse and (short >= hypotenuse or long >= hypotenuse):
                        raise ValueError("Not allowed by the rules of math.")
                    
                    1 Reply Last reply Reply Quote 0
                    • OkieWolf
                      OkieWolf last edited by

                      Agreed. It works fine if short and long are the same number, which equals 45 degrees.

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

                        Here’s what I came up with. It’s much shorter and easier to understand and I GREATLY appreciate all the help and patience.
                        This version does all the other one did plus more. This version will calculate the other side and angle based on two sides input and can now calculate any side of the triangle based on angle and any one of the three sides.

                        def button3_tapped(sender):
                        	hypotenuse = float(v['hypotenuse'].text or 0)
                        	short = float(v['short'].text or 0)
                        	long = float(v['long'].text or 0)
                        	angle = float(v['angle'].text or 0)
                        	if len([x for x in (hypotenuse, short, long, angle) if x]) != 2:
                        		v['mess'].text = "Enter two fields"
                        		v['mess'].background_color = 'red'
                        		v['mess'].text_color = 'white'
                        		return
                        	if hypotenuse and not angle:
                        		if short and not long:
                        			v['long'].text = str(math.sqrt(hypotenuse ** 2 - short ** 2))
                        			v['long'].text_color = 'green'
                        			v['angle'].text = str(math.degrees(math.asin(short / hypotenuse)))
                        			v['angle'].text_color = 'green'
                        		elif long and not short:
                        			v['short'].text = str(math.sqrt(hypotenuse ** 2 - long ** 2))
                        			v['short'].text_color = 'green'
                        			v['angle'].text = str(math.degrees(math.acos(long / hypotenuse)))
                        			v['angle'].text_color = 'green'
                        	else:
                        		if not angle:
                        			v['hypotenuse'].text = str(math.sqrt(short ** 2 + long ** 2))
                        			v['hypotenuse'].text_color = 'green'
                        			v['angle'].text = str(math.degrees(math.atan(short / long)))
                        			v['angle'].text_color = 'green'
                        		
                        	if angle:
                        		angle = math.radians(angle)
                        		if short and not long and not hypotenuse:
                        			v['hypotenuse'].text = str(short / (math.sin(angle)))
                        			v['hypotenuse'].text_color = 'green'
                        			v['long'].text = str(short / (math.tan(angle)))
                        			v['long'].text_color = 'green'
                        		elif long and not short and not hypotenuse:
                        			v['hypotenuse'].text = str(long / (math.cos(angle)))
                        			v['hypotenuse'].text_color = 'green'
                        			v['short'].text = str(long * (math.tan(angle)))
                        			v['short'].text_color = 'green'
                        		elif angle and hypotenuse and not long and not short:
                        			v['short'].text = str(hypotenuse * (math.sin(angle)))
                        			v['short'].text_color = 'green'
                        			v['long'].text = str(hypotenuse * (math.cos(angle)))
                        			v['long'].text_color = 'green' 
                        
                        1 Reply Last reply Reply Quote 0
                        • ccc
                          ccc last edited by

                          Please put the trailing three backticks on a line all by themselves.

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

                            @ccc
                            Done

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

                              OK. Now it is time to separate the business logic from the UI representation. We would need to put all the math logic in a function of the form:

                              def triangle(a, b, hypotenuse=0, angle=45):
                                  pass  # math logic goes here
                              

                              Where triangle(3, 4) returns (3, 4, 5.0, 45)
                              Where triangle(3, 0) would raise ValueError()

                              OkieWolf 1 Reply Last reply Reply Quote 0
                              • JonB
                                JonB last edited by

                                It seems to me you could also dispense with most of the long / short specific logic, and just compute the other edge, then figure out which one is the long vs short after the fact.

                                1 Reply Last reply Reply Quote 1
                                • OkieWolf
                                  OkieWolf @ccc last edited by OkieWolf

                                  @ccc

                                  Please explain

                                  def triangle(a, b, hypotenuse=0, angle=45):
                                      pass  # math logic goes here
                                  Where triangle(3, 4) returns (3, 4, 5.0, 45)
                                  Where triangle(3, 0) would raise ValueError() 
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • ccc
                                    ccc last edited by

                                    This was an invitation for you or someone else to write a function that can take between 2 and 4 parameters and calculate all other variables or raise an exception if there is no possible solution. This function would allow us to isolate all UI operations from all math operations. It would make it easier to test our math operations without the UI and would allow us to easily port the math operations to a different platform.

                                    OkieWolf 2 Replies Last reply Reply Quote 0
                                    • OkieWolf
                                      OkieWolf @ccc last edited by OkieWolf

                                      @ccc

                                      Below will calculate short and long with given hypotenuse and angle but you have to enter zero for short and long input.

                                      import math
                                      
                                      def triangle(short, long, hypotenuse, angle):
                                          pass  
                                          if hypotenuse and angle:
                                          	angle = math.radians(angle)
                                          	print ('Short = ' + str(hypotenuse * (math.sin(angle))))
                                          	print ('Long = ' + str(hypotenuse * (math.cos(angle))))
                                          	
                                      triangle(0,0,10,30)
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • OkieWolf
                                        OkieWolf @ccc last edited by

                                        @ccc

                                        This will calculate any side or angle. But input still has to be zero for unknowns at input.

                                        import math
                                        
                                        def triangle(short, long, hypotenuse, angle):
                                            pass
                                            if len([x for x in (hypotenuse, short, long, angle) if x]) == 2:
                                            	if hypotenuse and angle:
                                            		angle = math.radians(angle)
                                            		print	('Short = ' + str(hypotenuse * (math.sin(angle))))
                                            		print	('Long = ' + str(hypotenuse * (math.cos(angle))))
                                            	elif long and angle:
                                            		angle = math.radians(angle)
                                            		print	('Short = ' + str(long * (math.tan(angle))))
                                            		print	('Hypotnuse = ' + str(long / (math.cos(angle))))
                                            	elif short and angle:
                                            		angle = math.radians(angle)
                                            		print	('Long = ' + str(short / (math.tan(angle))))
                                            		print	('Hypotnuse = ' + str(short / (math.sin(angle))))
                                            	elif hypotenuse and short:
                                            		print ('Long = ' + str(math.sqrt(hypotenuse ** 2 - short ** 2)))
                                            		print ('Angle = ' + str(math.degrees(math.asin(short / hypotenuse))))
                                            	elif hypotenuse and long:
                                            		print ('Short = ' + str(math.sqrt(hypotenuse ** 2 - long ** 2)))
                                            		print ('Angle = ' + str(math.degrees(math.acos(long / hypotenuse))))
                                            	elif short and long:
                                            		print ('Hypotenuse = ' + str(math.sqrt(short ** 2 + long ** 2)))
                                            		print ('Angle = ' + str(math.degrees(math.atan(short / long))))
                                            else:
                                            	print ("ERROR")
                                        
                                        triangle(5,0,10,0) 
                                        
                                        1 Reply Last reply Reply Quote 0
                                        • ccc
                                          ccc last edited by ccc

                                          Step 0: drop the pass line.
                                          Step 1:

                                              if len([x for x in (hypotenuse, short, long, angle) if x]) != 2:
                                                  raise ValueError("Exactly two parameters must be zero.")
                                          

                                          Step 2: change triangle() so it never prints but instead returns the answer with the statement return short, long, hypotenuse, angle
                                          Step 3: change triangle(5,0,10,0) to print(triangle(5,0,10,0)).

                                          Step 1: is called a fast-fail which is safer and more readable than failing later in the function. Basically is says "I see a bad situation (bad input data) so I am going to raise an exception and stop processing".

                                          mikael OkieWolf 2 Replies Last reply Reply Quote 0
                                          • mikael
                                            mikael @ccc last edited by

                                            @ccc, I am sure I just saw you using count somewhere:

                                            if (hyp, ...).count(0) != 2:
                                                raise ...
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors