什么是弃用的unicode字符数组的替换?

时间:2017-10-29 06:15:43

标签: python-3.x unicode

unicode字符数组可用作可变字符串:

import array

ins = "Aéí"
ms = array.array('u', ins)
ms[0] = "ä"
outs = ms.tounicode()
# äéí

但是从Python 3.3开始不推荐使用类型'u'。什么是现代替代品?

我能做到:

ms = list(ins)
# mutate
outs = ''.join(ms)

但是我发现与数组相比,字符列表的内存效率非常低。

可替换地:

ms = array.array('L', (ord(ch) for ch in ins))
ms[0] = ord("ä")
outs = "".join(chr(ch) for ch in ms)

但它的可读性远远低于已弃用的原版。

3 个答案:

答案 0 :(得分:1)

这与您的上一个示例类似,但是以更具可读性和效率的方式初始化数组。您必须选择大小为四个字节的数组大小。 Iunsigned int的代码,在大多数操作系统上是4个字节。为了便于携带,您可能希望以编程方式选择此值。

#!coding:utf8
import array
import sys

# Verifying the item size.
assert array.array('I').itemsize == 4

# Choose encoding base on native endianness:
encoding = 'utf-32le' if sys.byteorder == 'little' else 'utf-32be'

ins = "Aéí"
ms = array.array('I',ins.encode(encoding))
ms[0] = ord('ä')
print(ms.tobytes().decode(encoding))

输出:

äéí

1000个元素字符串的计时显示速度要快得多:

In [7]: s = ''.join(chr(x) for x in range(1000))

In [8]: %timeit ms = array.array('I',s.encode('utf-32le'))
1.77 µs ± 14.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [9]: %timeit ms = array.array('I',(ord(x) for x in s))
167 µs ± 5.35 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [21]: %timeit outs = "".join(chr(x) for x in ms)
194 µs ± 4.98 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [23]: %timeit outs = ms.tobytes().decode('utf-32le')
3.92 µs ± 97 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

但你可能会过度思考它。我不知道你正在处理什么字符串大小,但只使用list(data)更快,如果内存效率更低,并且它不是那么糟糕。这是一个非BMP字符列表(~1M),以及不可变字符串切片,变异数组和变异列表的时间:

In [67]: data = ''.join(chr(x) for x in range(0x10000,0x110000))

In [68]: ms = array.array('I',data.encode('utf-32le'))

In [69]: %%timeit global data
    ...: data = data[:500] + 'a' + data[501:]
    ...:
3.33 ms ± 235 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [70]: %timeit ms[500] = ord('a')
73.6 ns ± 0.433 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [71]: %%timeit v = list(data)
    ...: v[500] = 'a'
    ...:
28.7 ns ± 0.144 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [72]: sys.getsizeof(data)
Out[72]: 4194380

In [73]: sys.getsizeof(ms)
Out[73]: 4456524

In [74]: sys.getsizeof(list(data))
Out[74]: 9437296

变换列表很简单,比变异数组快3倍,而且只使用了2倍的内存。

答案 1 :(得分:0)

Python3中的替换是str,内置类型。字符串是 Unicode 代码点的不可变序列。

因此,无需使用array('u', ...)str就足够了。

顺便说一下,删除'u'(在内部使用PyUnicode*)的原因是Py_UNICODE*表示被弃用且效率低下;在性能或内存敏感的情况下应该避免使用它。

答案 2 :(得分:0)

Python 3.3+已经不再单独使用Unicode了。因为PEP393,这就是为什么一切都可以表达并用作str。

Here如何处理后Python 3.3解释器中的Unicode处理。根据定义 -

  

Unicode标准描述了代码如何表示字符   点。代码点是整数值,通常用16表示。   在标准中,使用符号U + 12CA来编写代码点   表示值为0x12ca(十进制4,810)的字符。 Unicode   标准包含很多列出字符及其表的表   相应的代码点:

最后,我不确定你想要达到什么目标,但是以下是否可以完成这项工作?

ins = "Aéí"
m = "ä" + ins[1:]
print(m)

在Python 3.5.2版本中,它为我提供了这个输出 -

äéí

如果有帮助,请告诉我

最后请注意,如果您想知道+运算符,那么here就是一个很好的SO帖子。投票最多的答案的要点是:如果您使用的是Cpython,最好使用+而不是append join等。

如果您想使用您的apprach,仍然有整个阵列模块available,其中包含您运行我们的代码所需的所有内容。我在python3.5中进行了测试,但它确实有效。

也有这种方式 -

a = "ä"
p = b"".join([a.encode('utf-8'), ins[1:].encode('utf-8')])
print(p.decode('utf-8'))  
相关问题