解决 Python 的字符串 center ljust rjust 在面对中文时的 bug
方法一:修改内置 str 的方法,能更灵活的定制,更准确地判断 CJK 字符,全局有效。甚至还能把转义序列也兼容了。
def modify_str():
import gc, ctypes
def curse(klass, attr, value):
"""
这里用的是 forbiddenfruit 库的 curse 简化了一下,省去了下载第三方库
用于修改内置 class 的属性
"""
dikt = gc.get_referents(klass.__dict__)[0]
old_value = dikt.get(attr, None)
old_name = '_c_%s' % attr
dikt[attr] = value
if old_value:
dikt[old_name] = old_value
dikt[attr].__name__ = old_value.__name__
dikt[attr].__qualname__ = old_value.__qualname__
ctypes.pythonapi.PyType_Modified(ctypes.py_object(klass))
CJK_CHARACTERS = [ # 定义 CJK 字符的区间
(0x3400, 0x4DB5), # CJK Unified Ideographs Extension A
(0x4E00, 0x9FA5), # CJK Unified Ideographs
(0x9FA6, 0x9FBB), # CJK Unified Ideographs
(0xF900, 0xFA2D), # CJK Compatibility Ideographs
(0xFA30, 0xFA6A), # CJK Compatibility Ideographs
(0xFA70, 0xFAD9), # CJK Compatibility Ideographs
(0x20000, 0x2A6D6), # CJK Unified Ideographs Extension B
(0x2F800, 0x2FA1D), # CJK Compatibility Supplement
(0xFF00, 0xFFEF), # 全角ASCII、全角中英文标点、半宽片假名、半宽平假名、半宽韩文字母
(0x2E80, 0x2EFF), # CJK部首补充
(0x3000, 0x303F), # CJK标点符号
(0x31C0, 0x31EF), # CJK笔划
(0x2F00, 0x2FDF), # 康熙部首
(0x2FF0, 0x2FFF), # 汉字结构描述字符
(0x3100, 0x312F), # 注音符号
(0x31A0, 0x31BF), # 注音符号(闽南语、客家语扩展)
(0x3040, 0x309F), # 日文平假名
(0x30A0, 0x30FF), # 日文片假名
(0x31F0, 0x31FF), # 日文片假名拼音扩展
(0xAC00, 0xD7AF), # 韩文拼音
(0x1100, 0x11FF), # 韩文字母
(0x3130, 0x318F), # 韩文兼容字母
(0x1D300, 0x1D35F), # 太玄经符号
(0x4DC0, 0x4DFF), # 易经六十四卦象
(0xA000, 0xA48F), # 彝文音节
(0xA490, 0xA4CF), # 彝文部首
(0x2800, 0x28FF), # 盲文符号
(0x3200, 0x32FF), # CJK字母及月份
(0x3300, 0x33FF), # CJK特殊符号(日期合并)
(0x2700, 0x27BF), # 装饰符号(非CJK专用)
(0x2600, 0x26FF), # 杂项符号(非CJK专用)
(0xFE10, 0xFE1F), # 中文竖排标点
(0xFE30, 0xFE4F), # CJK兼容符号(竖排变体、下划线、顿号)
]
CJK_CHARACTERS.sort()
CJK_CHARACTERS_LIST = [a for tup in CJK_CHARACTERS for a in tup]
def char_width(char):
'''按一个 CJK 占两个宽度算,返回字符宽度'''
unicode = ord(char)
if unicode < CJK_CHARACTERS_LIST[0]:
return 1
for index, item in enumerate(CJK_CHARACTERS_LIST):
if unicode < item: break
if index % 2:
return 2
return 1
def calculate(string):
'''字符串总宽度'''
return sum([char_width(char) for char in string])
import re
csi_pattern = re.compile("(?:\x9b|\033\[)\d*(?:;\d*)*[A-Za-z]") # 用于匹配转义序列
# 重新定义 str 的三个方法:
def center(self: str, width, *args, **kwargs):
width += sum([len(csi) for csi in csi_pattern.findall(self)]) # 加上转义序列的补偿
if len(self) < width:
width -= (calculate(self) - len(self))
return getattr(self, '_c_'+'center')(width, *args, **kwargs)
def ljust(self: str, width, *args, **kwargs):
if len(self) < width:
width -= (calculate(self) - len(self))
return getattr(self, '_c_'+'ljust')(width, *args, **kwargs)
def rjust(self: str, width, *args, **kwargs):
if len(self) < width:
width -= (calculate(self) - len(self))
return getattr(self, '_c_'+'rjust')(width, *args, **kwargs)
curse(str, 'center', center)
curse(str, 'ljust', ljust)
curse(str, 'rjust', rjust)
modify_str()
print('这是中文字符'.center(30, '*'))
print('这是\x9b42m绿色背景\x9b0m字符'.center(30, '*'))
print('English Words'.center(30, '*'))
print('Привет! Как дела?'.center(30, '*'))

方法二:先用 gbk 编码,调整后,再解码。局限性较大,不能准确判断 CJK 符号,不易兼容其它国家的语言。
# 一般中文宽度是英文的两倍,带有中文的字符串使用 center ljust rjust 会出现宽度非常不一致
# 我们希望中文可以按两个宽度计算
# 可以利用 gbk 是双字节编码,中文字符占2字节,英文字符占1字节
# 将字符串用 gbk 编码后,再用 center ljust rjust,最后用 gbk 解码,就可以得到视觉上中英文一致的宽度
# 需要注意的是,有一些偏僻字使用 gbk 是无法编码的,例如:
print('\x9b42m 展示 \x9b0m')
print('这是中文字符'.encode('gbk').center(30, b'*').decode('gbk'))
print('English Words'.encode('gbk').center(30, b'*').decode('gbk'))
解决 Python 的字符串 center ljust rjust 在面对中文时的 bug的更多相关文章
- 解决python中write()函数向文件中写中文时出现乱码的问题
今天看<python编程从入门到实践>的第10章文件.异常,在做练习的时候,向文件中写内容,但是写中文就不行,后来在百度上查了众多资料,解决方法如下: 解决:在open()函数中添加一个e ...
- python center, ljust, rjust
例子 >>> s = "jihite" >>> s.center(, "*") '**jihite**' >>& ...
- 【python】 字符串转小写(含汉字等时仍work)
def mylower(str): outstr = ""; strlen = len(str); idx = 0; while idx < strlen: if ord(s ...
- Python: ljust()|rjust()|center()字符串对齐
通过某种对齐方式来格式化字符串 ①对于基本的操作,可以使用字符串的ljust(),rjust(),center() ②函数format()同样可以用来很容易的对齐字符串,使用<,>,~
- python之字符串
字符串与文本操作 字符串: Python 2和Python 3最大的差别就在于字符串 Python 2中字符串是byte的有序序列 Python 3中字符串是unicode的有序序列 字符串是不可变的 ...
- Python数据类型——字符串
概论 字符串顾名思义就是一串字符,由于Python中没有“字符”这种数据类型,所以单个的字符也依然是字符串类型的.字符串可以包含一切数据,无论是能从键盘上找到的,还是你根本都不认识的.与数一样,字符串 ...
- python基础-字符串(str)类型及内置方法
字符串-str 用途:多用于记录描述性的内容 定义方法: # 可用'','''''',"","""""" 都可以用于定义 ...
- python中字符串内置方法
字符串类型 作用:定义姓名.性别等 定义方式: s='lzs' #\n换行 \t缩进4个空格 \r回退上一个打印结果,覆盖上一个打印结果 加上一个\让后面的\变得无意义 内置方法: (优先掌握) 1. ...
- python之字符串,列表,字典,元组,集合内置方法总结
目录 数字类型的内置方法 整型/浮点型 字符串类型的内置方法 列表的内置方法 字典的内置方法 元组的内置方法 集合类型内置方法 布尔类型 数据类型总结 数字类型的内置方法 整型/浮点型 加 + 减 - ...
- Python格式化字符串~转
Python格式化字符串 在编写程序的过程中,经常需要进行格式化输出,每次用每次查.干脆就在这里整理一下,以便索引. 格式化操作符(%) "%"是Python风格的字符串格式化操作 ...
随机推荐
- 全新TI AM62xx系列核心板上市,小小身板蕴藏巨大势能!
2011年TI推出AM335x,成为了此后市场上最受欢迎的通用工业级ARM处理器,并广泛应用于工业HMI, 医疗电子,机器人,能源,汽车等领域.随着工业4.0的发展,HMI人机交互.工业工控.医疗等领 ...
- nginx学习之路
nginx反向代理服务器 1.技术选型 nginx主要能实现的功能有负载均衡,反向代理,动静分离.选择nginx主要为了实现反向代理以及负载均衡功能, *为什么要实现反向代理 传统项目直接暴露在外网入 ...
- linux 安装配置redis
linux 安装配置redis 安装 官网下载地址:https://redis.io/download linux下载命令:wget http://download.redis.io/releases ...
- Oracle-安装问题:Win10系统离线安装framework3.5报0x8024402c的问题
Oracle-安装问题:Win10系统离线安装framework3.5报0x8024402c的问题 像神州信用政府版本相关的系统都不允许联网,也就需要离线安装下,Net3.5之类的文件 具体步骤可以参 ...
- [极客大挑战 2019]Http 1
进入题目,可以看到是一个小型的网站 这里我也走了很多弯路,题目提示为HTTP,这里就可以在源码中找一些隐藏信息 搜搜.php可以看到有一个Secret.php 进入提示It doesn't come ...
- JavaWeb学习笔记第二弹
(续集)DQL:查询操作 1.排序查询 排序方式:(仅有一个排序参照时) 1.升序:ASC(默认) 命令:**select * from 表名 order by 列名 (asc);** 2.降序:DE ...
- MySQL学习(五)事务
参考博客:https://www.cnblogs.com/kismetv/p/10331633.html 0.提交和回滚 注:mysql默认自动开启了事务. -- 手动开启事务 start trans ...
- 基于Pierre Dellacherie的俄罗斯方块-05Pierre Dellacherie算法
基于Pierre Dellacherie的俄罗斯方块-05Pierre Dellacherie算法 Pierre Dellacherie算法感觉上像是一个遍历算法,给与各个参数不同的权重,使得更加合理 ...
- 使用chatgt(GPT-4)将过程式(的java代码)改成函数式(的elixir代码)
天啦噜太可怕了,之前我还嘲笑chatgpt不会小众语言来着. chatgt(GPT-4)在接收2次prompt后,把过程式(的java代码)改成了函数式(的elixir代码),给出的Elixir代码可 ...
- springboot多环境开发兼容问题(Maven和boot)
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven ...