2016-03-19 7 views
0

Ich versuche, die Hauptdatei meines Python-Programms zu optimieren, aber es gibt eine "Unbound local Error: lokale Variable 'sider' vor der Zuweisung verwiesen". Ich bin nicht sicher, wie dies geschieht, da die Variable "angle" an derselben Stelle ist, aber es funktioniert. Jede Hilfe wird geschätzt!Ungebundener lokaler Fehler in Python

from getdata import * 
from trifun import * 


def main(): 
    outfile = open("SFout.txt", "w") 
    myList = getData() 
    # print(myList) 

    names = myList[0] 
    vertices = myList[1] 

    for i in range(len(names)): 
     x1 = vertices[i][0][0] 
     y1 = vertices[i][0][1] 
     x2 = vertices[i][1][0] 
     y2 = vertices[i][1][1] 
     x3 = vertices[i][2][0] 
     y3 = vertices[i][2][1] 
     print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3)) 
     print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3), file = outfile) 



     if duplicatePts(vertices[i]): 
      print("You have duplicate points, not a triangle") 
      outfile.write("You have duplicate points, not a triangle \n \n") 
      print("\n") 
      continue 

     if collinear(vertices[i]): 
      print("The points are collinear, not a triangle") 
      outfile.write("\nThe points are collinear, not a triangle \n \n") 
      print("\n") 
      continue 

     v = findAllSides(vertices[i]) 
     pm = str("%.1f" % (perimeter(vertices[i]))) 
     print("Perimeter: ", pm.ljust(25), end="") 
     print("Perimeter: ", pm.ljust(25), end="", file = outfile) 

     s = ("Sidelengths %0.2f, %0.2f, %0.2f" % (v[0], v[1], v[2])) 
     sidelength1 = str("%.1f" % (v[0])) 
     sidelength2 = str("%.1f" % (v[1])) 
     sidelength3 = str("%.1f" % (v[2])) 
     side = sidelength1 + "," + sidelength2 + "," + sidelength3 
     print("Side lengths: ", side) 
     print("Side lengths: ", side, file=outfile) 
     #outfile.write("Side length:" + side + '\n') 

     if acute(vertices[i]): 
      angle = "Acute" 
      # print("Acute") 
      #   outfile.write("\nAcute") 
     elif right(vertices[i]): 
      angle = "Right" 
     #   print("Right") 
     #   outfile.write("\nRight") 
     elif obtuse(vertices[i]): 
      angle = "Obtuse" 
     #   print("Obtuse") 
     #   outfile.write("\nObtuse") 
     if Scalene(vertices[i]): 
      side = "Scalene" 
     #   print("Scalene") 
     #   outfile.write("\nScalene") 
     elif Equilateral(vertices[i]): 
      side = "Equilateral" 
     #   print("Equilateral") 
     #   outfile.write("\nEquilateral") 
     elif Isosceles(vertices[i]): 
      side = "Isosceles" 
     #   print("Isosceles") 
     #   outfile.write("\nIsosceles") 
     # f.close() 
     print((angle + " & " + side).ljust(37), end="") 
     print((angle + " & " + side).ljust(37), end="", file=outfile) 

     #outfile.write(angle + " & " + side+"\n") 
     print("Area is: %0.2f" % area(vertices[i])) 
     print("Area is: %0.2f" % area(vertices[i]), "\n", file=outfile) 

     #outfile.write("Area is: %0.2f" % area(vertices[i])+"\n") 
     print("\n") 
    outfile.close() 


main() 

getData

def getData(): 
    names = [] 
    vertices = [] 
    myList = [names,vertices] 
    with open("test.txt") as f: 
     for line in f: 
      x = line.split() 
      names.append(x[0]) 
      x1 = float(x[1]) 
      y1 = float(x[2]) 
      x2 = float(x[3]) 
      y2 = float(x[4]) 
      x3 = float(x[5]) 
      y3 = float(x[6]) 

      vertices.append([[x1,y1],[x2,y2],[x3,y3]]) 

     return myList 

Trifun

# The text file contains vertices of three points of a triangle, separated by a space. 

# Import Math for calculations. 
import math 


# This function checks if there are any duplicate points in te vertices of the triangle. 
# If there are, it s not a triangle. 
def duplicatePts(vertices): 
    #vertices looks like this : [[x1,y1],[x2,y2],[x3,y3]] 
    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    if (x1,y1)==(x2,y2) or (x2, y2) == (x3, y3) or (x1, y1) == (x3, y3): 
     return True 
    else: 
     return False 


# This function checks if the points of the triangle are collinear. 
# Triangle points cannot be in the same line. They have to be in different positions on the lane. 
def collinear(vertices): 


    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    if (x2 - x1) == 0: 
     # As discussed in class, set it to a high number, to assume it is vertical 
     slope1 = 9999 
    else: 
     slope1 = (y2 - y1)/(x2 - x1) 
    if (x3 - x2) == 0: 
     # As discussed in class, set it to a high number, to assume it is vertical 
     slope2 = 9999 
    else: 
     slope2 = (y3 - y2)/(x3 - x2) 

    if slope1 == slope2: 
     return True 
    else: 
     return False 


# To find the perimeter, we need to find the sides first. 
# Perimeter = Sum of all three sides 
def perimeter(vertices): 

    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 
    perimeter = sideAB + sideAC + sideBC 
    return perimeter 

# Finding the length of the side using the distance formula. 
def sideLength(x1, y1, x2, y2): 

    length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) 
    return length 


# Using the min function to find out the shortest side. 
def findAllSides(vertices): 

    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 
    lst=[sideAB, sideAC, sideBC] 

    return lst 




# We know how to find the sides now. 

# We determine if the triangle is a right triangle by using Pythagoras theorem. 
# Pythagoras theorem states that a triangle is a right triangle when 
# Square of Hypotenus is equal to the sum of other two sides. 
def typeObtuseRightAcute(vertices): 
    #no idea if this is a good value but works for example 
    #and should be low enough to give right answers for all but crazy close triangles 
    epsilon=10**-8 
    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 
    # Using Pythagoras theorem 
    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 

    #use this instead 
    [var1,var2,largest] = sorted([sideAB, sideBC, sideAC]) 



    if abs((largest) ** 2-((var1 ** 2 + (var2) ** 2)))<epsilon: 
     return "right" 
    elif (largest) ** 2 > ((var1 ** 2 + (var2) ** 2)): 
     return "obtuse" 
    else: 
     return "acute" 

def acute(vertices): 
    return typeObtuseRightAcute(vertices)=="acute" 

def right(vertices): 
    return typeObtuseRightAcute(vertices)=="right" 

def obtuse(vertices): 
    return typeObtuseRightAcute(vertices)=="obtuse" 

# A triangle is a scalene triangle, when all three sides are not equal to each other. 
def Scalene(vertices): 
    EPSILON = 0.000001 
    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 
    if (abs(sideAB-sideBC)>=EPSILON and abs(sideBC-sideAC)>=EPSILON and abs(sideAB-sideAC)>=EPSILON): 
     return True 


# A triangle is an isosceles triangle when 2 of the sides are equal. 
def Isosceles(vertices): 
    EPSILON = 0.000001 
    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 
    if (abs(sideAB-sideBC)<EPSILON or abs(sideBC-sideAC)<EPSILON or abs(sideAB-sideAC)<EPSILON) and not (abs(sideAB-sideBC)<EPSILON and abs(sideBC-sideAC)<EPSILON and abs(sideAB-sideAC)<EPSILON): 
     return True # or True 
    else: 
     return False 


# A triangle is an equilateral triangle when all three sides are equal to each other. 
def Equilateral(vertices): 
    EPSILON = 0.000001 
    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 

    if (abs(sideAB-sideBC)<EPSILON and abs(sideBC-sideAC)<EPSILON and abs(sideAB-sideAC)<EPSILON): 
     return True 
    else: 
     return False 

# To find the area, we need to find the semi perimeter first. 
# We find the area of triangle using Heron's formula. 
def area(vertices): 

    x1 = vertices[0][0] 
    y1 = vertices[0][1] 
    x2 = vertices[1][0] 
    y2 = vertices[1][1] 
    x3 = vertices[2][0] 
    y3 = vertices[2][1] 

    sideAB = sideLength(x1, y1, x2, y2) 
    sideBC = sideLength(x2, y2, x3, y3) 
    sideAC = sideLength(x3, y3, x1, y1) 
    semiPerimeter = (sideAB + sideBC + sideAC)/2 

    area = (semiPerimeter * (semiPerimeter - sideAB) * (semiPerimeter - sideBC) * (semiPerimeter - sideAC)) ** 0.5 

    return area 

Textdatei

Alpha -4 0 4 0 0 6.9282 
Bravo -2.161 -3.366 2.161 3.366 -5.83 3.743 
Charlie 3.54 5.46 -4.54 5.557 3.1 -2.1 
Delta 0 4 0 2 0 2 
Echo -4 3 1 3 6 3 
Foxtrot 0 0 5 1 10 0 
Golf 0 4 0 0 4 0 
+0

Vielleicht gibt es einen Punkt, an dem die bedingte Anweisung für 'sider' nicht ausgeführt wird, während die bedingte Anweisung von' angle' ausgeführt wird. Sie können versuchen, die Kurzschrift verwenden, wenn, siehe diesen Link: http://stackoverflow.com/questions/14029245/python-putting-an-if-elif-else-statement-on-one-line oder andere Die Option besteht darin, eine initialisierte lokale Variable oben wie 'sider = ''' zu deklarieren, bevor sie in anderen Teilen der Methode verwendet wird. – Chisskarzz

+0

Ich denke nicht, dass sonst hier funktionieren würde, da wir drei Funktionen aufrufen eine andere Datei. Gibt es eine Möglichkeit, dieses Format beizubehalten und dennoch Sider arbeiten zu lassen? –

+0

Das wird passieren, wenn keine der drei Bedingungen zutrifft. –

Antwort

0

Ich bin mir nicht sicher, ob dies können Sie zufrieden machen, aber dies davon ab, ein verhindern kann Unbound Local Error:

sider = ("Scalene" 
     if scalene(vertices[i]) 
     else ("Equilateral" 
       if equilateral(vertices[i]) 
       else ("Isosceles" 
        if isosceles(vertices[i]) 
        else "None of the above") 
       ) 
     ) 

oder wenn Sie das Format beibehalten möchten und nur um sicher zu sein, nur eine Initialisierung der lokalen Variablen machen sider:

def main(): 
    outfile = open("SFout.txt", "w") 
    myList = getData() 

    names = myList[0] 
    vertices = myList[1] 
    sider = '' # declare this one 
    angle = '' # and this one 

    for i in range(len(names)): 
     x1 = vertices[i][0][0] 
     y1 = vertices[i][0][1] 
     x2 = vertices[i][1][0] 
     y2 = vertices[i][1][1] 
     x3 = vertices[i][2][0] 
     y3 = vertices[i][2][1] 
     print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3)) 
     print((names[i]), (x1, y1), ",", (x2, y2), ",", (x3, y3), file=outfile) 

.... 
+0

Der erste sollte Winkel sein und nicht sider und ich versuchte den zweiten und es gab mir einen ValueError –

+0

Bereits einige Korrekturen vorgenommen. Wird der erste erfolgreich ausgeführt? In welcher Zeile tritt der ValueError auf? Können Sie die genaue Nachricht des ValueError geben? – Chisskarzz

+0

Nein und immer noch nicht. Ich habe jetzt mein gesamtes Programm hochgeladen und Sie können sehen, wie ich vorgehe. Es hat 3 Dateien. Eine Hauptdatei und zwei weitere Python-Dateien. Ich habe Probleme damit, dass die Dreiecke als gleichseitige und gleichschenklige Skalen gleichgesetzt werden. Es gibt eine Textdatei, aus der das Python-Programm liest. –

0

Es würde helfen, die Rückverfolgung mit Ihrer Frage zu liefern. Ich nehme an, der Fehler tritt bei der print((angle ...)-Anweisung auf. Alle Funktionen scalene(), equilateral() oder isosceles() müssen False zurückgeben. Um das fehlerhafte Dreieck zu finden, fügen Sie einen else Block wie folgt hinzu, um die Scheitelpunkte zu drucken.

if scalene(vertices[i]): 
    sider = "Scalene" 

elif equilateral(vertices[i]): 
    sider = "Equilateral" 

elif isosceles(vertices[i]): 
    sider = "Isosceles" 

else: 
    # this should never happen 
    print("Something's wrong!") 
    print(vertices[i]) 

EDIT Hier ist das Problem: typeEquilateralIsoscelesScalene (Eckpunkte) gibt "E quilateral", aber in equilateral() Sie es vergleichen, um zu "e quilateral". Gleiches gilt für scalene() und isosceles().

+0

Das hat nicht funktioniert, aber ich habe jetzt mein gesamtes Programm hochgeladen und Sie können sehen, wie ich vorgehe. Es hat 3 Dateien. Eine Hauptdatei und zwei weitere Python-Dateien. Ich habe Probleme damit, dass die Dreiecke als gleichseitige und gleichschenklige Skalen gleichgesetzt werden.Es gibt eine Textdatei, aus der das Python-Programm liest. –

+0

Was hat es gedruckt? – RootTwo

+0

UnboundLocalError: Lokale Variable 'sider', auf die vor der Zuweisung verwiesen wird –