为什么我的python for循环中没有定义我的变量?

时间:2013-01-13 20:19:39

标签: python

以下是代码:

import math
with open("test.stl") as file:
    vertices = [map(float, line.split()[1:4])
                for line in file
                if line.lstrip().startswith('vertex')]

    normals = [map(float, line.split()[2:5])
                for line in file
                if line.lstrip().startswith('facet')]

V=len(vertices)
ordering=[]
N=len(normals)

for i in range(0,N):
    p1=vertices[3*i]
    p2=vertices[3*i+1]
    p3=verticies[3*i+2]
    print p1

    x1=p1[0]
    y1=p1[1]
    z1=p1[2]

    x2=p2[0]
    y2=p2[1]
    z2=p2[2]

    x3=p3[0]
    y3=p3[1]
    z3=p3[2]

    a=[x2-x1,y2-y1,z2-z1]
    b=[x3-x1,y3-y1,z3-z1]

    a1=x2-x1
    a2=y2-y1
    a3=z2-z1
    b1=x3-x1
    b2=y3-y1
    b3=z3-z1

    normal=normals[i]

    cross_vector=[a2*b3-a3*b2,a3*b1-a1*b3,a1*b2-a2*b1]

    if cross_vector==normal:
        ordering.append([i,i+1,i+2])
    else:
        ordering.append([i,i+2,i+1])
print ordering
print cross_vector

如果我尝试在for循环中添加print p1(或任何其他变量,如cross_vector),则没有任何错误但没有输出,如果我尝试在for循环之外打印它们,它说NameError:未定义名称'(变量名称)'。因此,如果没有定义这些变量,显然我的排序数组打印为[](空白)。我怎么能改变这个。变量是否必须在定义之前声明?

编辑:以下是运行上述代码时的错误输出:

Traceback (most recent call last):
  File "convert.py", line 52, in <module>
    print cross_vector
NameError: name 'cross_vector' is not defined

如上所述,这发生在for循环中定义的任何变量,我只是使用cross_vector作为示例。

3 个答案:

答案 0 :(得分:6)

这一行:

vertices = [map(float, line.split()[1:4])
            for line in file
            if line.lstrip().startswith('vertex')]

读取文件中的所有行。在那之后,你就在文件的末尾,没有什么可读的了。所以

normals = [map(float, line.split()[2:5])
            for line in file
            if line.lstrip().startswith('facet')]

为空(normals == [])。因此

N=len(normals)

N设置为0,表示此循环:

for i in range(0,N):

永远不会执行。这就是为什么从里面打印什么都不做的原因 - 循环没有运行。

答案 1 :(得分:3)

要解决DSM诊断出的问题,请使用:

import math
import itertools
with open("test.stl") as file:
    i1, i2 = itertools.tee(file)
    vertices = [map(float, line.split()[1:4])
                for line in i1
                if line.lstrip().startswith('vertex')]

    normals = [map(float, line.split()[2:5])
                for line in i2
                if line.lstrip().startswith('facet')]

您可能还想尝试删除列表推导,并在整个过程中使用迭代器,以节省大文件的内存。


编辑:

目前,您将整个文件加载到内存中,然后在内存中再创建两个完整大小的列表。相反,您可以按照只需要从内存中的文件读取的方式编写它。例如,我们可以用 generator comprehensions替换列表推导:

import math
import itertools
with open("test.stl") as file:
    i1, i2 = itertools.tee(file)
    vertexIter = (map(float, line.split()[1:4])
                  for line in i1
                  if line.lstrip().startswith('vertex'))

    normalIter = (map(float, line.split()[2:5])
                  for line in i2
                  if line.lstrip().startswith('facet'))

在这里,我们完全避免使用任何内存。

要使其有用,您需要能够从以下位置替换循环:

for i in range(0,N):
    p1=vertices[3*i]
    p2=vertices[3*i+1]
    p3=verticies[3*i+2]
    normal = normals[i]

    # processing

到单个迭代器:

for normal, p1, p2, p3 in myMagicIterator:
    # processing

我能想到的一种方法是:

myMagicIterator = itertools.izip(
    normalIter,
    itertools.islice(vertexIter, 0, 3),
    itertools.islice(vertexIter, 1, 3),
    itertools.islice(vertexIter, 2, 3)
)

迭代器等效于:

myNormalList = zip(normals, vertices[0::3], vertices[1::3], vertices[2::3])

答案 2 :(得分:0)

在它之外声明它们(在for循环之前)并看看会发生什么。即使在for循环中声明它们也没关系,但是当循环不运行时,你可能希望它们具有“默认”值。

如果需要,请尝试发布很多较小的示例。