这可能是一个非常绿色的问题,但我希望你理解 - 刚开始使用python并尝试改进。无论如何,写了一个小函数来做“Shoelace方法”,在笛卡尔平面上找到多边形的区域(参见this进行复习)。
我想知道如何改进我的方法,所以我可以尝试新的方式来做同样的旧事。
def shoelace(list):
r_p = 0 # Positive Values
r_n = 0 # Negative Values
x, y = [i[0] for i in list], [i[1] for i in list]
x.append(x[0]), y.append(y[0])
print(x, y)
for i in range(len(x)):
if (i+1) < len(x):
r_p += (x[i] * y[i+1])
r_n += (x[i+1] * y[i])
else:
break
return ((abs(r_p - r_n))/2)
答案 0 :(得分:2)
不要使用需要注释的短变量名;使用表示功能的名称。
list
是内置列表类型的名称,所以虽然Python会让你替换这个名字,但这在风格上是个坏主意。
,
不应该用于分隔应该是什么语句。您可以使用;
,但通常更好的方法是将内容放在不同的行上。在您的情况下,它恰好起作用,因为您使用.append
作为副作用,但基本上您正在做的是构建2元组(None, None)
(来自.append
的返回值)扔掉它。
尽可能使用内置函数进行标准列表转换。例如,请参阅zip
的文档。除非你真的不需要进行这种转变;你想要考虑成对的相邻点,所以这样做 - 并在循环内拆开它们的坐标。
但是,您可以使用zip
将点列表转换为相邻点对的列表:)这样可以让您编写更清晰的循环。这个想法很简单:首先,我们列出相对于原件的所有“下一个”点,然后我们zip
将两个点列表放在一起。
return
不是一个函数,所以你return
的东西不需要包围括号。
不是计算单独的正值和负值,而是对单个值执行带符号算术。
def shoelace(points):
signed_double_area = 0
next_points = points[1:] + points[:1]
for begin, end in zip(points, next_points):
begin_x, begin_y = begin
end_x, end_y = end
signed_double_area += begin_x * end_y
signed_double_area -= end_x * begin_y
return abs(signed_double_area) / 2
答案 1 :(得分:0)
从功能上讲,你的程序非常好。一个小问题是将range(len(x))
替换为xrange(len(x))
。它使程序稍微更有效率。通常,只有在您确实需要其创建的完整值列表的情况下,才应使用range
。如果您只需要遍历这些值,请使用xrange
。
此外,您不需要return
语句中的括号,也不需要r_p +=
和r_n +=
语句中的括号。
关于样式,在Python中,变量赋值不应该像你那样完成,而是在=
符号的每一边都有一个空格:
r_p = 0
r_n = 0