发布时间:2019/10/17 16:33:13   更新时间:2020/07/31 19:49:25
本文官网地址:https://docs.blender.org/api/current/info_best_practice.html
本文基于Blender2.80。
提示:译解是指翻译和注解。【注解】是作者的一些个人解释,用【】符号括起来。
在编写自己的脚本时,python非常适合新开发人员使用并提高工作效率,但您也可以养成奇怪的习惯,或者至少编写不容易被他人理解的脚本。
对于您自己的工作,这当然很好,但是如果您想与他人合作或将您的工作包含在blender中,我们鼓励您采取一些做法。
对于Blender / Python开发,我们选择遵循python建议的样式指南,以避免在我们自己的脚本之间混合样式,并使其更易于使用其他项目中的python脚本。
如果您最终希望将它们添加到Blender中,则将我们的样式指南用于您自己的脚本可以使工作更加轻松。
此样式指南称为pep8,可在此处找到
pep8标准的简短列表。
* 类名称的骆驼帽:MyClass
* 所有小写??的下划线下划线模块名称:my_module
* 缩进4个空格(无制表符)
* 运算符周围的空格。,1 + 1而不是1+1
* 仅使用显式导入(不导入*)
* 不要使用单行:if val: body,而是分成两行。
和pep8一样,我们还有其他用于Blender Python脚本的约定。
* 枚举使用单引号,字符串使用双引号。
两者当然都是字符串,但是在我们内部的API中,枚举是有限集合中的唯一项。例如。
bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.filepath = "//render_out"
* pep8还定义了行数不能超过79个字符,我们认为这过于严格,因此每个脚本都是可选的。
我们会定期检查Blender脚本是否符合pep8,对于要包含在此检查中的脚本,请在脚本顶部将该行添加为注释。
#
<pep8
compliant>
要启用行长检查,请改用此选项。
#
<pep8-80
compliant>
* 编写UI布局时要记住的一些注意事项:
UI代码非常简单。可以使用布局声明轻松创建体面的布局。
此处的一般规则:如果需要更多的代码用于布局声明,那么对于实际属性,您就做错了。
布局示例:
* layout()
基本布局是简单的Top->Bottom布局。
layout.prop()
layout.prop()
* layout.row()
如果要在一行中包含多个属性,请使用row()。
row = layout.row()
row.prop()
row.prop()
* layout.column()
如果要在列中使用属性,请使用column()。
col = layout.column()
col.prop()
col.prop()
* layout.split()
这可用于创建更复杂的布局。例如,您可以拆分布局并创建两个彼此相邻的column()布局。当您只需要连续两个属性时,请不要使用split。为此使用row()。
split = layout.split()
col = split.column()
col.prop()
col.prop()
col = split.column()
col.prop()
col.prop()
声明名称:
尝试仅将这些变量名称用于布局声明:
* row()布局的行
* column()布局的列
* 拆分为split()布局
* column_flow()布局的流程
* sub布局(例如,列内的一列)的子布局
在Python中,有一些方便的列表功能,这些功能使您不必在列表中进行搜索。
即使您没有遍历python所遍历的列表数据,但是您需要注意那些通过搜索整个列表来降低脚本速度的函数。
my_list.count(list_item)
my_list.index(list_item)
my_list.remove(list_item)
if list_item in my_list: ...
在python中,我们可以在列表中添加和删除列表,当修改列表长度时,这会比较慢,尤其是在列表的开头,因为修改索引之后的所有数据都需要上移或下移1位。
添加到列表末尾的最简单方法是使用 my_list.append(list_item)或my_list.extend(some_list),而删除项目最快的方法是my_list.pop()或。del my_list[-1]
要使用索引,可以使用或 用于删除列表,但是速度较慢。my_list.insert(index,
list_item)list.pop(index)
有时它更快(但需要更多的内存)来重建列表。
假设您要删除列表中的所有三角形多边形。
而不是…
polygons = mesh.polygons[:] # make a list copy of the meshes polygons
p_idx = len(polygons) # Loop backwards
while p_idx: # while the value is not 0
p_idx -= 1
if len(polygons[p_idx].vertices) == 3:
polygons.pop(p_idx) # remove the triangle
使用列表理解来构建新列表更快。
polygons = [p for p in mesh.polygons if len(p.vertices) != 3]
如果您有一个列表要添加到另一个列表,而不是…
for l in some_list:
my_list.append(l)
采用…
my_list.extend([a, b, c...])
请注意,可以在需要时使用插入,但是它比添加要慢,尤其是在长列表的开头插入时。
此示例显示了制作反向列表的非常次优的方式。
reverse_list = []
for list_item in some_list:
reverse_list.insert(0, list_item)
Python提供了更方便的方法来使用slice方法来反转列表,但是您可能需要在过多依赖它之前对其进行计时:
some_reversed_list = some_list[::-1]
使用my_list.pop(index)而不是my_list.remove(list_item)
这要求您具有列表项的索引,但是要更快,因为remove()它将搜索列表。
这是一个如何在1个循环中删除项目,如何先删除最后一个项目的示例,这样做速度更快(如上所述)。
list_index = len(my_list)
while list_index:
list_index -= 1
if my_list[list_index].some_test_attribute == 1:
my_list.pop(list_index)
此示例显示了一种删除项目的快速方法,用于在不破坏脚本功能的情况下可以更改列表顺序的情况。这可以通过交换2个列表项来实现,因此您删除的项始终是最后一个。
pop_index = 5
# swap so the pop_index is last.
my_list[-1], my_list[pop_index] = my_list[pop_index], my_list[-1]
# remove last item (pop_index)
my_list.pop()
当删除大列表中的许多项目时,这可以提供良好的加速效果。
将列表/字典传递给函数时,让函数修改列表而不是返回新列表会更快,因此python不必在内存中复制列表。
就地修改列表的功能比创建新列表的功能更有效。
这通常比较慢,因此仅在有意义的情况下才使用函数,而不用修改列表。
>>> my_list = some_list_func(my_list)
由于没有重新分配和列表重复,因此通常更快。
>>> some_list_func(vec)
还要注意,传递切片列表会在Python内存中复制列表。
>>> foobar(my_list[:])
如果my_list是一个大型数组,其中包含10000个项目,那么一个副本可能会占用大量额外的内存。
这是将多个字符串连接为一个字符串进行写入的3种方法。这也适用于代码中涉及大量字符串连接的任何区域。
String addition-这是最慢的选项,如果可以帮助不要使用,尤其是在循环写入数据时。
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
String formatting -从浮点数和整数写入字符串数据时,请使用此选项。
>>> file.write("%s %s %s\n" % (str1, str2, str3))
String join() function 用于连接字符串列表(该列表可能是临时的)。在以下示例中,字符串之间使用空格“”连接,其他示例为“”或“,”。
>>> file.write(" ".join([str1, str2, str3, "\n"]))
Join在许多字符串上最快, 字符串格式 也相当快(转换数据类型更好)。字符串算术最慢。
由于许多文件格式都是ASCII,因此解析/导出字符串的方式可能会极大地影响脚本的运行速度。
将字符串导入Blender时,有几种解析字符串的方法。
使用float(string)而不是eval(string),如果您知道该值将是一个int,则int(string)float()也会对一个int起作用,但是使用int()读取int的速度更快。
如果您要检查关键字的字符串开头,而不是…
>>> if line[0:5] == "vert ": ...
采用…
>>> if line.startswith("vert "):
使用startswith()速度稍快(大约5%),还避免了切片长度与字符串长度不匹配的可能的错误。
my_string.endswith(“ foo_bar”)也可以用于行尾。
如果不确定文本是大写还是小写,请使用lower()或upper()字符串功能。
>>> if line.lower().startswith("vert ")
在尝试语句是有用的,以节省时间编写错误校验码。
但是try的速度比if慢得多,因为每次都必须设置一个异常,因此请避免在循环执行并运行多次的代码区域中使用try。
在某些情况下,使用try比检查条件是否会引发错误更快,因此值得尝试。
Python有两种比较值的方式,和的区别是可以运行对象比较功能,而比较标识,即两个变量都引用内存中的同一项目。a == ba is b==__cmp__()is
如果您知道要检查从多个位置引用的相同值,is则速度会更快。
在开发脚本时,最好是及时安排它以了解性能的任何变化,这可以轻松完成。
import time
time_start = time.time()
# do something...
print("My Script Finished: %.4f sec" % (time.time() - time_start))