社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

生成遍历顺序对比说明文档 python代码

GISAI • 1 月前 • 120 次点击  

# -*- coding: utf-8 -*-

"""

生成遍历顺序对比说明文档 (docx)

"""

importos

importmatplotlib

matplotlib.use('Agg')

matplotlib.rcParams['font.sans-serif'= ['Microsoft YaHei''SimSun''KaiTi']

matplotlib.rcParams['axes.unicode_minus'=False

importmatplotlib.pyplotasplt

importmatplotlib.patchesasmpatches

frommatplotlib.patchesimportFancyBboxPatch

import numpy asnp

from docx import Document

from docx.shared import Inches, Pt, Cm, RGBColor

from docx.enum.text import WD_ALIGN_PARAGRAPH

from docx.enum.table import WD_TABLE_ALIGNMENT


# ========== 配置 ==========

ROWSCOLS=45

OUT_DIR=r'C:\Users\yl\Desktop'

IMG_DIR=os.path.join(OUT_DIR'_temp_imgs')

os.makedirs(IMG_DIRexist_ok=True)


# ========== 画图工具函数 ==========


defdraw_grid_with_arrows(axordertitlesubtitleorder_name

                          arrow_color='#E74C3C'cell_bg='#F0F3F4',

                          highlight_color='#FADBD8'text_color= '#2C3E50'):

    """绘制带箭头和序号的网格图"""

    ax.set_xlim(-0.1COLS-0.05)

    ax.set_ylim(-0.1ROWS-0.05)

    ax.set_aspect('equal')

    ax.axis('off')

    

    # 标题

    ax.text(COLS/2ROWS+0.5titlefontsize=14fontweight='bold',

            ha='center'va='center'color=text_color,

            bbox=dict(boxstyle='round,pad=0.3'facecolor='#EBF5FB'alpha=0.8))

    ax.text(COLS/2ROWS+0.15subtitlefontsize=10,

            ha='center'va='center'color='#7F8C8D')

    

    # 绘制单元格

    forrinrange(ROWS):

        forcinrange(COLS):

            idx=order[rc]

            # 根据顺序深浅着色

            alpha=0.3+0.7* ( idx/ (ROWS*COLS-1))

            color=plt.cm.RdYlGn_r(alpha)

            rect=FancyBboxPatch((cROWS-1-r), 11

                                   boxstyle="square,pad=0",

                                   facecolor=coloredgecolor='#BDC3C7',

                                   linewidth=1.5)

            ax.add_patch(rect)

            

            # 序号文字

            ax.text(c+0.5ROWS-1-r+0.5str(idx+1),

                    ha='center'va='center'fontsize=11fontweight='bold',

                    color='#2C3E50')

    

    # 绘制箭头连线

    order_list= []

    forrinrange(ROWS):

        forcinrange(COLS):

            order_list.append((cROWS-1-r))

    

    foriinrange(len(order_list-1):

        x1y1=order_list[i]

        x2y2=order_list[i+1]

        ax.annotate(''xy=(x2+0.5y2+0.5), xytext=(x1+0.5y1+0.5),

                     arrowprops=dict(arrowstyle='->'color=arrow_color,

                                    lw=1.5alpha=0.6))

    

    # 添加顺序名称标签

    ax.text(0.05-0.4f'→ {order_name}'fontsize=9fontweight='bold',

            color=arrow_colortransform=ax.transData)



defdraw_comparison_grid(axordertitleorder_namearrow_color):

    """绘制对比图(两个网格并排中的单个)"""

    ax.set_xlim(-0.1COLS-0.05)

    ax.set_ylim(-0.1ROWS-0.05)

    ax.set_aspect('equal')

    ax.axis('off')

    

    ax.text(COLS/2ROWS+ 0.3titlefontsize=11fontweight='bold',

            ha='center'va='center'color='#2C3E50')

    

    forrinrange(ROWS):

        forcinrange(COLS):

            idx=order[rc]

            alpha=0.3+0.7* (idx/ (ROWS*COLS-1))

            color=plt.cm.RdYlGn_r(alpha)

            rect=FancyBboxPatch((cROWS-1-r), 11,

                                   boxstyle="square,pad=0",

                                   facecolor=coloredgecolor='#BDC3C7',

                                   linewidth=1)

            ax.add_patch(rect)

            ax.text(c+0.5ROWS-1-r+0.5str(idx+1),

                    ha='center'va='center'fontsize=9fontweight='bold',

                     color='#2C3E50')

    

    order_list= []

    forrinrange(ROWS):

        forcinrange(COLS):

            order_list.append((cROWS-1-r))

    

    foriinrange(len(order_list-1):

        x1y1=order_list[i]

        x2y2=order_list[i+1]

        ax.annotate(''xy=(x2+0.5y2+0.5), xytext=(x1+0.5y1+0.5),

                     arrowprops=dict(arrowstyle='->'color=arrow_color,

                                    lw=1alpha=0.5))



# ========== 生成图片 ==========


# 1. 从左到右,从上到下(行优先)

order_row=np.zeros((ROWSCOLS), dtype=int)

forrinrange(ROWS):

    forcinrange(COLS):

        order_row[rc =r*COLS+c


fig1ax1=plt.subplots(11figsize=(87), dpi=150)

draw_grid_with_arrows(ax1order_row

                       '方式一:从左到右 → 从上到下',

                       '(行优先 / Row-Major Order)',

                       '行优先遍历')

fig1.savefig(os.path.join(IMG_DIR'row_major.png'), bbox_inches='tight'pad_inches=0.3)

plt.close(fig1)


# 2. 从上到下,从左到右(列优先)

order_col=np.zeros((ROWSCOLS), dtype=int)

forcinrange(COLS):

    forrinrange(ROWS):

        order_col[rc=c*ROWS+r


fig2ax2=plt.subplots(11figsize=(87), dpi=150)

draw_grid_with_arrows(ax2order_col,

                       '方式二:从上到下 ↓ 从左到右',

                       '(列优先 / Column-Major Order)',

                       '列优先遍历',

                       arrow_color= '#3498DB')

fig2.savefig(os.path.join(IMG_DIR'col_major.png'), bbox_inches='tight'pad_inches=0.3)

plt.close(fig2)


# 3. 对比图

fig3axes=plt.subplots(12figsize=(147), dpi=150)

draw_comparison_grid(axes[0], order_row,

                     '从左到右,从上到下\n(行优先)',

                     '行优先''#E74C3C')

draw_comparison_grid(axes[1], order_col,

                     '从上到下,从左到右\n(列优先)',

                     '列优先''#3498DB')

fig3.suptitle('两种遍历顺序对比'fontsize=16fontweight='bold'y=1.02)

fig3.savefig(os.path.join(IMG_DIR'comparison.png'), bbox_inches='tight'pad_inches=0.3)

plt.close(fig3)



# ========== 生成 Word 文档 ==========

doc= Document()


# 页面设置

forsectionindoc.sections:

    section.page_width = Cm(21 )

    section.page_height = Cm(29.7)

    section.left_margin = Cm(2.5)

    section.right_margin = Cm(2.5)

    section.top_margin = Cm(2)

    section.bottom_margin = Cm(2)


# 标题

title=doc.add_heading('二维网格遍历顺序对比说明'level=0)

title.alignment = WD_ALIGN_PARAGRAPH.CENTER


doc.add_paragraph('')  # 空行


# ===== 一、概述 =====

doc.add_heading('一、概述'level=1)

p=doc.add_paragraph()

p.add_run('在二维网格(矩阵、栅格、图像像素等)中遍历所有单元格时,有两种最基本的遍历顺序:')


t=doc.add_table(rows=2cols=2)

t.style ='Light Grid Accent 1'

t.alignment = WD_TABLE_ALIGNMENT.CENTER

t.cell(00).text ='方式'

t.cell(01).text ='说明'

t.cell(10).text ='从左到右,从上到下'

t.cell(11).text ='先遍历完当前行的所有列,再换到下一行(行优先 / Row-Major)'

# 设置表格字体

forrowint.rows:

    forcellinrow.cells:

        forparagraphincell.paragraphs:

            forruninparagraph.runs:

                run.font.size =  Pt(11)


doc.add_paragraph('')


# ===== 二、详细说明 =====

doc.add_heading('二、方式一:从左到右,从上到下(行优先)'level=1)


doc.add_paragraph('遍历规则:')

p=doc.add_paragraph('每一行内,从左向右依次访问每个单元格'style='List Bullet')

p=doc.add_paragraph('当前行访问完毕后,换到下一行,继续从左到右'style='List Bullet')

p=doc.add_paragraph('所有行从上到下依次处理'style='List Bullet')


doc.add_paragraph('访问顺序公式:')

p=doc.add_paragraph()

run=p.add_run('index = row × 列数 + col')

run.font.name ='Consolas'

run.font.size = Pt(11)

run.font.color.rgb = RGBColor(0x2C0x3E0x50)


doc.add_paragraph('')

doc.add_paragraph('图示:')

doc.add_picture(os.path.join(IMG_DIR'row_major.png'), width=Cm(16))


doc.add_paragraph('')

doc.add_heading('三、方式二:从上到下,从左到右(列优先)'level=1)


doc.add_paragraph('遍历规则:')

p=doc.add_paragraph('每一列内,从上向下依次访问每个单元格'style='List Bullet')

p=doc.add_paragraph('当前列访问完毕后,换到下一列,继续从上到下'style='List Bullet')

p=doc .add_paragraph('所有列从左到右依次处理'style='List Bullet')


doc.add_paragraph('访问顺序公式:')

p=doc.add_paragraph()

run=p.add_run('index = col × 行数 + row')

run.font.name ='Consolas'

run.font.size = Pt(11)

run.font.color.rgb = RGBColor(0x2C0x3E0x50)


doc.add_paragraph('')

doc.add_paragraph('图示:')

doc.add_picture(os.path.join(IMG_DIR'col_major.png'), width=Cm(16))


# ===== 四、对比 =====

doc.add_heading('四、对比总结'level=1)


doc.add_paragraph('')

doc.add_paragraph('两种遍历顺序的直观对比:')

doc.add_paragraph('')

doc.add_picture(os.path.join(IMG_DIR'comparison.png'), width=Cm(16))


doc.add_paragraph('')


# 对比表格

t2=doc.add_table(rows=6cols=3)

t2.style ='Light Grid Accent 1'

t2.alignment = WD_TABLE_ALIGNMENT.CENTER

headers= ['对比项''从左到右 → 从上到下(行优先)''从上到下 ↓ 从左到右(列优先)']

data= [

    ['遍历方向''行内水平移动为主''列内垂直移动为主'],

    ['内存访问' '行内连续访问,缓存友好''列内跳跃访问,缓存不友好'],

    ['适用场景''C/C++/Python 数组、图像处理''Fortran/MATLAB 数组、GIS 栅格'],

    ['循环嵌套''外层 for row,内层 for col''外层 for col,内层 for row'],

    ['别名''Row-Major Order''Column-Major Order'],

]


forjhinenumerate(headers):

    cell=t2.cell(0j)

    cell.text =h

    forpincell.paragraphs:

        forruninp.runs:

            run.font.bold =True

            run.font.size = Pt(10)


forirow_datainenumerate(data):

    forjvalinenumerate(row_data):

        cell=t2.cell(i+1j)

        cell.text =val

        forpincell.paragraphs:

            forruninp.runs:

                run.font.size = Pt(10)


doc.add_paragraph('')


# ===== 五、示例代码 =====

doc.add_heading('五、代码示例'level=1)


doc.add_heading('5.1 行优先(从左到右,从上到下)'level=2)

code1="""# C / Python 风格 — 行优先

for row in range(ROWS):        # 外层:行(从上到下)

    for col in range(COLS):    # 内层:列(从左到右)

        visit(grid[row][col])

# 访问顺序:(0,0)→(0,1)→(0,2)→...→(1,0)→(1,1)→..."""

p=doc.add_paragraph()

run=p.add_run(code1)

run.font.name ='Consolas'

run.font.size = Pt(9)

run.font.color.rgb = RGBColor(0x2C0x3E0x50)


doc.add_heading('5.2 列优先(从上到下,从左到右)'level=2)

code2="""# 列优先遍历

for col in range(COLS):        # 外层:列(从左到右)

    for row in range(ROWS):    # 内层:行(从上到下)

        visit(grid[row][col])

# 访问顺序:(0,0)→(1,0)→(2,0)→...→(0,1)→(1,1)→..."""

p=doc.add_paragraph()

run=p.add_run(code2)

run.font.name ='Consolas'

run.font.size = Pt(9)

run.font.color.rgb = RGBColor(0x2C0x3E0x50)


# ===== 六、注意事项 =====

doc.add_heading('六、注意事项'level=1)

notes= [

    '行优先是 C、C++、Python(NumPy 默认)等语言的数组存储方式',

    '列优先是 Fortran、MATLAB、R 等语言的数组存储方式',

    '在 GIS 栅格数据处理中,两种遍历方式都常见,需注意数据格式要求的存储顺序',

    '行优先遍历时,相邻访问的内存地址连续,CPU 缓存命中率更高,性能通常更好',

    '选择哪种遍历方式取决于具体应用场景和数据存储格式',

]

fornoteinnotes:

    doc.add_paragraph(notestyle='List Bullet')


# 保存

out_path=os.path.join(OUT_DIR'遍历顺序对比说明_新.docx')

doc.save(out_path)

print(f'Document saved: {out_path }')


# 清理临时图片

importshutil

shutil.rmtree(IMG_DIR)

print('Temp images cleaned up.')



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/196871