简体   繁体   English

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

[英]Why aren't my variables being defined in my python for loop?

Here is the code: 这是代码:

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

If I try to add print p1 (or any of the other variables such as cross_vector) inside of the for loop, there aren't any errors but no output and if I try to print them outside of the for loop it says NameError: name '(variable name)' is not defined. 如果我尝试在for循环内添加print p1(或任何其他变量,例如cross_vector),则不会出现任何错误,但没有输出,如果我尝试在for循环外打印它们,则会显示NameError:name未定义'(变量名)'。 So if none of these variables are being defined, obviously my ordering array prints as [] (blank). 因此,如果这些变量均未定义,显然我的排序数组将打印为[](空白)。 How can I change this. 我该如何更改。 Do variables have to be declared before they are defined? 在定义变量之前是否必须先声明变量?

Edit: Here is the error output when the code above is run: 编辑:这是上面的代码运行时的错误输出:

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

As explained above this happens with any variable defined in the for loop, I am just using cross_vector as an example. 如上所述,在for循环中定义的任何变量都会发生这种情况,我仅以cross_vector为例。

This line: 这行:

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

reads through all the lines in the file. 读取文件中的所有行。 After that, you're at the end of the file, and there's nothing left to read. 之后,您位于文件的结尾,没有什么可读取的。 So 所以

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

is empty ( normals == [] ). 为空( normals == [] )。 Thus 从而

N=len(normals)

sets N to 0, meaning that this loop: N设置为0,表示此循环:

for i in range(0,N):

is never executed. 永远不会执行。 That's why printing from inside it does nothing -- the loop isn't being run. 这就是为什么从内部打印不执行任何操作的原因-循环未运行。

To solve the problem diagnosed by DSM, use: 要解决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')]

You might also want to try and drop the list comprehension, and work with iterators throughout, to save on memory for large files. 您可能还想尝试放弃列表理解,并在整个过程中使用迭代器,以节省大文件的内存。


Edit: 编辑:

At present, you load the entire file into memory, and then create two more full size lists in memory. 当前,您将整个文件加载到内存中,然后在内存中创建两个以上的完整大小列表。 Instead, you can write it in a way that only reads from the file in memory as required. 相反,您可以按照只从内存中的文件读取的方式来编写它。 As an example, we can replace the list comprehensions with 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'))

Here, we've avoided using any memory at all. 在这里,我们完全避免使用任何内存。

For this to be useful, you need to be able to replace your loop, from: 为了使它有用,您需要能够从以下位置替换循环:

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

    # processing

To a single iterator: 对于单个迭代器:

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

One way I can think of doing this is: 我可以想到的一种方法是:

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

Which is the iterator equivalent of: 迭代器等效于:

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

Declare them outside of it (before the for loop) and see what happens. 在其外部声明它们(在for循环之前),然后看看会发生什么。 Even if it would be ok to declare them in the for loop, you would probably like to have a "default" value of them when the loop doesn't run. 即使可以在for循环中声明它们,也可以在不运行循环时将它们的值设置为“默认”。

And please try to post a lot smaller example if necessary. 并请尝试,如果有必要张贴小了很多例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM