You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python curses是否存在与C curses中chtype字符串等效的实现?

Python curses 实现预定义带属性字符串的方案

在C curses中,我们可以通过chtype类型(通常为unsigned int)存储字符及其关联属性,预定义好带属性的字符串后,只需调用一次addchstr()就能复用,代码简洁高效。示例如下:

#include <curses.h>

static const chtype hello[] = {
    'H' | A_BOLD,
    'e' | COLOR_PAIR(1) | A_UNDERLINE,
    'l' | COLOR_PAIR(2) | A_REVERSE,
    'l' | COLOR_PAIR(3) | A_ITALIC,
    'o',
    ' ' | COLOR_PAIR(1),
    'W' | COLOR_PAIR(2) | A_BOLD,
    'o' | COLOR_PAIR(3) | A_STANDOUT,
    'r' | A_BOLD,
    'l' | COLOR_PAIR(1) | A_ITALIC | A_UNDERLINE | A_BLINK,
    'd' | COLOR_PAIR(2),
    '!' | COLOR_PAIR(3) | A_BOLD | A_REVERSE | A_UNDERLINE | A_ITALIC,
    '\0'
};

int main(void){
    initscr();
    start_color();
    cbreak();
    noecho();
    curs_set(0);
    
    use_default_colors();
    init_pair(1, COLOR_YELLOW, COLOR_BLUE);
    init_pair(2, COLOR_WHITE, COLOR_GREEN);
    init_pair(3, COLOR_RED, COLOR_CYAN);

    addchstr(hello);
    refresh();
    getch();

    endwin();
    return 0;
}

但在Python curses中,仅支持单个带属性字符的输出(如c = ord('A') | curses.A_BOLD; stdscr.addch(c)),没有直接对应addchstr()的方法,只能通过分段调用addstr()处理属性相同的子串,操作繁琐。以下是几种实现「预定义后轻松复用」的变通方案:

方案1:模拟C风格的属性字符序列,批量调用addch()

将每个带属性的字符以ord(字符) | 属性的形式存入列表,封装一个批量输出的函数,定义一次即可重复调用:

import curses

# 预定义带属性的字符序列
hello = [
    ord('H') | curses.A_BOLD,
    ord('e') | curses.color_pair(1) | curses.A_UNDERLINE,
    ord('l') | curses.color_pair(2) | curses.A_REVERSE,
    ord('l') | curses.color_pair(3) | curses.A_ITALIC,
    ord('o'),
    ord(' ') | curses.color_pair(1),
    ord('W') | curses.color_pair(2) | curses.A_BOLD,
    ord('o') | curses.color_pair(3) | curses.A_STANDOUT,
    ord('r') | curses.A_BOLD,
    ord('l') | curses.color_pair(1) | curses.A_ITALIC | curses.A_UNDERLINE | curses.A_BLINK,
    ord('d') | curses.color_pair(2),
    ord('!') | curses.color_pair(3) | curses.A_BOLD | curses.A_REVERSE | curses.A_UNDERLINE | curses.A_ITALIC,
]

def add_chstr(win, ch_seq):
    for ch in ch_seq:
        win.addch(ch)

def main(stdscr):
    curses.start_color()
    curses.cbreak()
    curses.noecho()
    curses.curs_set(0)
    
    curses.use_default_colors()
    curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLUE)
    curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_GREEN)
    curses.init_pair(3, curses.COLOR_RED, curses.COLOR_CYAN)

    add_chstr(stdscr, hello)
    stdscr.refresh()
    stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(main)

方案2:封装「子串+属性」元组列表,批量调用addstr()

将相同属性的连续子串与属性打包成元组,存入列表后批量输出,相比逐个调用addch()能减少函数调用次数,性能更优:

import curses

# 预定义(子串, 属性)元组列表
hello_parts = [
    ('H', curses.A_BOLD),
    ('e', curses.color_pair(1) | curses.A_UNDERLINE),
    ('l', curses.color_pair(2) | curses.A_REVERSE),
    ('l', curses.color_pair(3) | curses.A_ITALIC),
    ('o', 0),
    (' ', curses.color_pair(1)),
    ('W', curses.color_pair(2) | curses.A_BOLD),
    ('o', curses.color_pair(3) | curses.A_STANDOUT),
    ('r', curses.A_BOLD),
    ('l', curses.color_pair(1) | curses.A_ITALIC | curses.A_UNDERLINE | curses.A_BLINK),
    ('d', curses.color_pair(2)),
    ('!', curses.color_pair(3) | curses.A_BOLD | curses.A_REVERSE | curses.A_UNDERLINE | curses.A_ITALIC),
]

def add_attr_str(win, parts):
    for s, attr in parts:
        win.addstr(s, attr)

def main(stdscr):
    curses.start_color()
    curses.cbreak()
    curses.noecho()
    curses.curs_set(0)
    
    curses.use_default_colors()
    curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLUE)
    curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_GREEN)
    curses.init_pair(3, curses.COLOR_RED, curses.COLOR_CYAN)

    add_attr_str(stdscr, hello_parts)
    stdscr.refresh()
    stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(main)

方案3:自定义类封装,支持更复杂的复用场景

如果需要对带属性字符串进行更灵活的管理(如指定输出位置、修改内容等),可以封装成自定义类,实现专属的绘制方法:

import curses

class AttrString:
    def __init__(self, parts):
        self.parts = parts
    
    def draw(self, win, y=0, x=0):
        win.move(y, x)
        for s, attr in self.parts:
            win.addstr(s, attr)

# 实例化预定义的带属性字符串
hello = AttrString([
    ('H', curses.A_BOLD),
    ('e', curses.color_pair(1) | curses.A_UNDERLINE),
    ('l', curses.color_pair(2) | curses.A_REVERSE),
    ('l', curses.color_pair(3) | curses.A_ITALIC),
    ('o', 0),
    (' ', curses.color_pair(1)),
    ('W', curses.color_pair(2) | curses.A_BOLD),
    ('o', curses.color_pair(3) | curses.A_STANDOUT),
    ('r', curses.A_BOLD),
    ('l', curses.color_pair(1) | curses.A_ITALIC | curses.A_UNDERLINE | curses.A_BLINK),
    ('d', curses.color_pair(2)),
    ('!', curses.color_pair(3) | curses.A_BOLD | curses.A_REVERSE | curses.A_UNDERLINE | curses.A_ITALIC),
])

def main(stdscr):
    curses.start_color()
    curses.cbreak()
    curses.noecho()
    curses.curs_set(0)
    
    curses.use_default_colors()
    curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLUE)
    curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_GREEN)
    curses.init_pair(3, curses.COLOR_RED, curses.COLOR_CYAN)

    hello.draw(stdscr)
    stdscr.refresh()
    stdscr.getch()

if __name__ == "__main__":
    curses.wrapper(main)

以上三种方案都能实现「定义一次,多次复用」的需求,无需每次输出时重复分段调用。其中方案1最贴近C curses的原生用法,方案2兼顾简洁性与性能,方案3适合复杂场景下的扩展。

内容的提问来源于stack exchange,提问作者user21711984

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 23:03:13