Cython学习六:字符串
直死之邪王灼眼
2019年08月20日 19:57
收录于文集
共51篇

最后用sqrt代替了python的指数运算:

这个结果也没有改进很多,看起来似乎这个程序已经没有什么改进的余地了。

Unicode and passing strings(Unicode码和传递字符串)

Similar to the string semantics in Python 3, Cython strictly separates byte strings and unicode strings. Above all, this means that by default there is no automatic conversion between byte strings and unicode strings (except for what Python 2 does in string operations). All encoding and decoding must pass through an explicit encoding/decoding step. To ease conversion between Python and C strings in simple cases, the module-level  and  directives can be used to implicitly insert these encoding/decoding steps.

类似于Python3中的字符串语义,Cython严格地区分字节字符串和unicode字符串。首先,这意味着在字节字符换和unicode字符串之间没有默认的自动转换(除了Python2有)。所有的编码和解码必须经过一个明确的编码和解码步骤。为了简化Python和C字符串之间的转换,c_string_type和c_string_encoding模块指令可以被用作含蓄地插入这些编码/解码步骤。

Python string types in Cython code(Cython代码中的Python字符串)

所谓字节字符串其实就是二进制字符,像b'10001&#​39;这种的。

Cython supports four Python string types:  and . The  and  types are the specific types known from normal Python 2.x (named  and  in Python 3). Additionally, Cython also supports the  type which behaves like the  type, except that it is mutable.

Cython支持四种Python字符串类型,bytes,str,unicode和basestring。bytes和unicode类型是特定的类型,它们从Python2开始引入(Python3中叫做bytes和str)。另外,Cython也支持bytearray类型,它像bytes类型一样,只不过它是可变的。

The  type is special in that it is the byte string in Python 2 and the Unicode string in Python 3 (for Cython code compiled with language level 2, i.e. the default). Meaning, it always corresponds exactly with the type that the Python runtime itself calls . Thus, in Python 2, both  and represent the byte string type, whereas in Python 3, both  and  represent the Python Unicode string type. The switch is made at C compile time, the Python version that is used to run Cython is not relevant.

str类型是特别的,因为它在Python2中是字节字符串,Python3中是unicode字符串(对于Cython代码编译按照语言等级2来编译,也就是默认的)。这意味着,它正好和Python运行时的str类型对应。因此,在Python2中,bytes和str都代表字节字符串类型,然而在Python3中,str和unicode都表示Python的Unicode字符串类型。这个选择是在C编译的时候做出的,和使用Python的版本是无关的。

When compiling Cython code with language level 3, the  type is identified with exactly the Unicode string type at Cython compile time, i.e. it does not identify with  when running in Python 2.

当使用语言等级3编译Cython代码时,在Cython编译的时候str类型正好被认作unicode字符串类型,也就是说在Python2中它不会被认作bytes。关于这个语言等级,查了查:cnblogs.com/signheart/p/4d2058ae687f9a29680c070de85f7fbe.html

其他 IDE 没有看到类似  的设置,所以这个功能应该算是 IntelliJ IDEA 特有的,可是 IntelliJ IDEA 官网也没有专门介绍  的地方,也许 IntelliJ IDEA 认为这个知识点属于 JDK 范畴所以没加以介绍吧。所以这里主要我对此的一些理解。我们应该知道 Java JDK 在每个新版本都会有其新特性,而新版本一般也会向下兼容旧版本的特性。这个语言等级就可以理解为是Cython编译器的版本吧。

Note that the  type is not compatible with the  type in Python 2, i.e. you cannot assign a Unicode string to a variable or argument that is typed . The attempt will result in either a compile time error (if detectable) or a  exception at runtime. You should therefore be careful when you statically type a string variable in code that must be compatible with Python 2, as this Python version allows a mix of byte strings and unicode strings for data and users normally expect code to be able to work with both. Code that only targets Python 3 can safely type variables and arguments as either  or .

注意str类型和Unicode类型在Python2中是不兼容的,也就是说你不能把一个unicode字符串赋值给一个str类型的变量或者参数。这种尝试会导致要么是编译时间错误(如果可以检查出来)或者一个运行时的类型错误异常。因此在代码中当你静态地给一个 字符串变量类型的时候,代码必须和Python2兼容,因为这个Python版本允许字节字符串和unicode字符串混合使用存储数据,用户可以正常希望代码可以一起运行。只针对Python3的代码可以安全地给变量或者参数指定类型为要么bytes要么是unicode。

The  type represents both the types  and , i.e. all Python text string types in Python 2 and Python 3. This can be used for typing text variables that normally contain Unicode text (at least in Python 3) but must additionally accept the  type in Python 2 for backwards compatibility reasons. It is not compatible with the  type. Its usage should be rare in normal Cython code as the generic  type (i.e. untyped code) will normally be good enough and has the additional advantage of supporting the assignment of string subtypes. Support for the type was added in Cython 0.20.

basestring类型可以表示str类型和unicode类型,也就是说所有Python2和Python3的Python文本字符串类型。这可以被用来测定文本变量的类型,文本里面正常地含有unicode文本(至少Python3)但是在Python2种必须额外接受str类型,这是为了向下兼容。这和bytes类型是不兼容地。它应该在一般地Cython代码中很少的使用,因为一般的object类型(也就是说没有定型的代码)已经足够好了,也有很多字符串子类型赋值的支持。对于basestring的支持在Cython0.20被引入。

String literals(字符串常量)

Cython understands all Python string type prefixes:

  • b'bytes&#​39; for byte strings

  • u'text&#​39; for Unicode strings

  • f'formatted {value}' for formatted Unicode string literals as defined by PEP 498 (added in Cython 0.24)

Unprefixed string literals become  objects when compiling with language level 2 and objects (i.e. Python 3 ) with language level 3.

Cython可以理解所有的Python字符类型前缀。

b'bytes&#​39;是二进制字符串

u'text&#​39;是unicode字符串

f'formatted {valued}&#​39;是格式化的unicode字符串常量,这个是在PEP498这个标准中定义的(在Cython0.24中加入的)。

没有前缀的字符串常量在使用语言等级2编译的时候是str对象,使用语言等级3的时候是unicode对象。

General notes about C strings(关于C字符串的注意)

In many use cases, C strings (a.k.a. character pointers) are slow and cumbersome. For one, they usually require manual memory management in one way or another, which makes it more likely to introduce bugs into your code.

在很多应用场景中,C字符串(又名字符指针)是很慢和复杂的。对于一个字符串,它们通常需要人工方式的内存管理,这使得它更可能给你的代码中引入bug。

Then, Python string objects cache their length, so requesting it (e.g. to validate the bounds of index access or when concatenating two strings into one) is an efficient constant time operation. In contrast, calling  to get this information from a C string takes linear time, which makes many operations on C strings rather costly.

然后,Python字符串对象储存它们的长度,所以查询(例如验证可访问索引的边界或者当把两个字符串连接成一个的时候)是高效的恒定时间的操作。相反,调用strlen从一个C字符串中得到这个信息花费线性时间。,这使得许多C字符串的操作都很费时间。

Regarding text processing, Python has built-in support for Unicode, which C lacks completely. If you are dealing with Unicode text, you are usually better off using Python Unicode string objects than trying to work with encoded data in C strings. Cython makes this quite easy and efficient.

忽视文本处理,Python有内置的对于unicode的支持,这是C完全缺乏的。因为C里面的字符都是ascii,并没有扩展到unicode,c只能打印出ascii码范围的字符。如果你在处理unicode文本,你最好使用Python unicode字符串对象而不是尝试用C字符串处理编码的数据。Cython使得整个很简单和高效。

Generally speaking: unless you know what you are doing, avoid using C strings where possible and use Python string objects instead. The obvious exception to this is when passing them back and forth from and to external C code. Also, C++ strings remember their length as well, so they can provide a suitable alternative to Python bytes objects in some cases, e.g. when reference counting is not needed within a well defined context.

一般来说:除非你知道你在做什么,如果可能,避免使用C的字符串,而是使用Python的字符串对象。明显的异常会出现在把它们传递给外部的C代码时。同样,C++字符串也储存它们的长度,所以它们可以在某些情况下合适的替代Python的bytes对象,例如在一个很好定义的场景下不需要引用计数的时候。

Passing byte strings(传递字节字符串)

we have dummy C functions declared in a file called  that we are going to reuse throughout this tutorial:

我们有仿造的C函数,声明在c_func.pyx中,我们将要在这个教程中贯穿使用:

strcpy是一个复制字符串的函数,要记住一点,C的字符串是要以\0结尾的,所以需要分配n+1个字符的空间。一个ascii字符需要一个字节,因为2^8=256。

We make a corresponding  to be able to cimport those functions:

我们创建了一个相应的c_func.pxd来使得可以cimport这些函数:

cdef char* c_call_returning_a_c_string()

cdef void get_a_c_string(char** c_string, Py_ssize_t *length)

It is very easy to pass byte strings between C code and Python. When receiving a byte string from a C library, you can let Cython convert it into a Python byte string by simply assigning it to a Python variable:

在C代码和Python中传递字节字符串是很容易的。当从C库中接收到一个字节字符串的时候,你可以让Cython通过简单的赋值给一个Python变量把它转换为Python的字节字符串。

from c_func cimport c_call_returning_a_c_string

cdef char* c_string = c_call_returning_a_c_string()

cdef bytes py_string = c_string

A type cast to object or bytes will do the same thing:

一个类型转换到Python对象或者bytes也会做同样的事情:

py_string = <bytes> c_string

This creates a Python byte string object that holds a copy of the original C string. It can be safely passed around in Python code, and will be garbage collected when the last reference to it goes out of scope. It is important to remember that null bytes in the string act as terminator character, as generally known from C. The above will therefore only work correctly for C strings that do not contain null bytes.

这创建了一个Python二进制字符串的对象,它是原始C字符串的一个副本。它可以被安全地在Python代码中传递,并且将会在它的最后一个引用超出范围之后被垃圾收集机制回收。记住空字符在字符串作为停止符是很重要的,也就是\0在C字符串中是停止符。因此上面只在不包含 空的C字符串bytes是正常运行的。

Besides not working for null bytes, the above is also very inefficient for long strings, since Cython has to call  on the C string first to find out the length by counting the bytes up to the terminating null byte. In many cases, the user code will know the length already, e.g. because a C function returned it. In this case, it is much more efficient to tell Cython the exact number of bytes by slicing the C string. Here is an example:

除了对于null bytes不正常以外,上面的对于长字符串也是不高效的,因为Cython没有必须首先调用strlen作用在C的字符串上通过计数直到停止的null字节来得到长度。在很多场景下,用户的代码可以事先直到长度,比如,因此一个C函数返回它。在这种情况下,通过对C字符串进行切片告诉Cython bytes的位数是更高效的。下面是一个例子:

Here, no additional byte counting is required and  bytes from the  will be copied into the Python bytes object, including any null bytes. Keep in mind that the slice indices are assumed to be accurate in this case and no bounds checking is done, so incorrect slice indices will lead to data corruption and crashes.

这里,不需要额外的字节计数,从C_string得到的长度将会被复制到Python的bytes对象中,抱恨任意个null bytes。时刻注意切片索引这种情况下被认为是正确的,没有做边界检查,所以不正确的切片索引会导致数据损坏和崩溃。

Note that the creation of the Python bytes string can fail with an exception, e.g. due to insufficient memory. If you need to  the string after the conversion, you should wrap the assignment in a try-finally construct:

注意创建一个Python bytes字符串可能会因为异常而失败,例如,因为内存不够。如果你需要f在转换以后free掉这个字符串,你应该把赋值放在一个try-finally结构里面:

To convert the byte string back into a C char*, use the opposite assignment:

为了把bytes字符串转换回一个C的char*,使用相反的赋值:

cdef char* other_c_string = py_string  # other_c_string is a 0-terminated string.

This is a very fast operation after which  points to the byte string buffer of the Python string itself. It is tied to the life time of the Python string. When the Python string is garbage collected, the pointer becomes invalid. It is therefore important to keep a reference to the Python string as long as the  is in use. Often enough, this only spans the call to a C function that receives the pointer as parameter. Special care must be taken, however, when the C function stores the pointer for later use. Apart from keeping a Python reference to the string object, no manual memory management is required.

这是一个非常快的操作,在这个操作之后other_c_string指向Python字符串的字节字符串缓冲区。它和Python字符串的生命周期挂钩。当Python字符串被垃圾回收机制回收以后,指针就变得无效了。因此只要char*还在使用,保持一个Python字符串的引用是重要的。经常,这仅仅是把C接收指针作为参数的函数的调用周期延长了。需要特别的关注是,然而,当C函数 储存指针以供以后使用。除了保持一个字符串对象的字符串引用之外,不需要人工的内存管理。

Starting with Cython 0.20, the  type is supported and coerces in the same way as the  type. However, when using it in a C context, special care must be taken not to grow or shrink the object buffer after converting it to a C string pointer. These modifications can change the internal buffer address, which will make the pointer invalid.

从Cython0.20开始,bytearray类型开始支持并且强迫以bytes类型处理。然而,当在C语言语境中使用的时候,注意不要在把它转化为C字符串指针之后增加或者减少对象的缓存区。这些改变可以内部的存储地址,这使得指针无效。

Accepting strings from Python code(从Python代码中接收字符串)

The other side, receiving input from Python code, may appear simple at first sight, as it only deals with objects. However, getting this right without making the API too narrow or too unsafe may not be entirely obvious.

另一方面,接收从Python代码的输入,这可能第一眼看起来简单,因此它仅仅处理对象。不过,正确地做到这件事而又不使得APi太勉强或者不安全可能不是那么明显。

In the case that the API only deals with byte strings, i.e. binary data or encoded text, it is best not to type the input argument as something like , because that would restrict the allowed input to exactly that type and exclude both subtypes and other kinds of byte containers, e.g. objects or memory views.

在API只处理bytes字符串的情况下,也就是说二进制数据或者编码的文本。最好不要把输入的参数定型,像bytes,因为那会把允许的输入限制到那种类型不包括子类型和其它种类的bytes容器,例如,bytearray对象或者memory views对象,它是一种Python类型,参考https://blog.csdn.net/rubikchen/article/details/80793103

Depending on how (and where) the data is being processed, it may be a good idea to instead receive a 1-dimensional memory view, e.g.

决定于怎样和哪里处理数据,接收一维的memory view可能是一个好的主意。

Cython’s memory views are described in more detail in Typed Memoryviews, but the above example already shows most of the relevant functionality for 1-dimensional byte views. They allow for efficient processing of arrays and accept anything that can unpack itself into a byte buffer, without intermediate copying. The processed content can finally be returned in the memory view itself (or a slice of it), but it is often better to copy the data back into a flat and simple  or  object, especially when only a small slice is returned. Since memoryviews do not copy the data, they would otherwise keep the entire original buffer alive. The general idea here is to be liberal with input by accepting any kind of byte buffer, but strict with output by returning a simple, well adapted object. This can simply be done as follows:

Cython的memory views在Typed Memoryviews里被描述了更多的细节,但是以上的例子已经显示了大部分的一维bytes views的相关功能。他们允许高效的数组处理并且接收任意可以分解成字节缓冲数据,没有中间的赋值。处理的内容最终可以返回到memory view自身类型(或者它的切片),但是更经常的是把数据拷贝到 一个平坦的简单的bytes或者bytearray对象,特别地,会仅仅返回一小部分切片。既然memoryviews没有复制数据,他们将会保持完整的初始缓冲区。一般的想法是对输入有一定的宽容,可以接收任意种类的byte缓冲,但是对于输出 很严格,通过返回一个简单的,适应性强的对象。这可以按照下面做:

If the byte input is actually encoded text, and the further processing should happen at the Unicode level, then the right thing to do is to decode the input straight away. This is almost only a problem in Python 2.x, where Python code expects that it can pass a byte string () with encoded text into a text API. Since this usually happens in more than one place in the module’s API, a helper function is almost always the way to go, since it allows for easy adaptation of the input normalisation process later.

如果byte的输入实际上是编码的文本,更进一步的处理应该发生在unicode等级,然后正确的做法是直接解码输入。这几乎仅仅是一个Python2的问题,Python代码期望的是它可以把解码后的文本byte字符串(str)传递到一个文本API。既然这通常发生在模块的不仅一个地方,一个帮助函数几乎总是必要的,既然它允许之后的简单的输入标准化处理的改变。

This kind of input normalisation function will commonly look similar to the following:

这种输入标准化函数看起来通常是类似下面的:

And should then be used like this:

并且接下来应该像这样使用:

Similarly, if the further processing happens at the byte level, but Unicode string input should be accepted, then the following might work, if you are using memory views:

类似地,如果进一步的处理发生在字节等级,unicode字符串输入应该被接收,然后接下来的可能起作用,如果你是用memory views:

In this case, you might want to additionally ensure that byte string input really uses the correct encoding, e.g. if you require pure ASCII input data, you can run over the buffer in a loop and check the highest bit of each byte. This should then also be done in the input normalisation function.

在这种情况下,你可能想要另外确保字节字符串输入真的使用了正确的编码,例如,如果你需要纯ASCII输入数据,你可以在一个缓冲区然后检测环里面使用然后检查每一个字节的最高位。这应该也在输入标准化函数中被完成。

我们先试验试验前面的程序:

c_func.pyx

看这个输出就是bytes类型,看起来上面的字节码应该是ASCII码,就是一个字节。Python里面表示二进制还是应该要带0b的开头。

0x是十六进制的前缀,0o是八进制的前缀,而且都是不加‘’的,也就是并不是字符串。eval函数里面加了是因为函数本身需要。

bin可以把十进制转换为二进制,而且其实转换出的是一个字符。

而bytes其实是ASCII码字符。前面说过Python3说过unicode和str类型一样。

上面的代码我在原来教程的基础上做了一些改变。

c_func1.pyx

其实length[0]=n挺有意思的,因为传递过来的是一个地址嘛,然后length[0]=*(length),所以说这个就相当于是*length=n。

用这个函数 c_call_returning_a_c_string和上一个的区别是上一个函数get_a_c_string还有一个长度的信息返回,而这里是没有的。

这个打不出来是因为windows系统输出和utf-8有区别而在ASCII范围内是一样的。

Dealing with “const”(处理常量)

Many C libraries use the  modifier in their API to declare that they will not modify a string, or to require that users must not modify a string they return, for example:

许多的C库在API中使用const修饰语来表示这个字符串不可以被改变或者用户不可以改变返回的字符串,例如:

Cython has support for the const modifier in the language, so you can declare the above functions straight away as follows:

Cython有对于const修饰符的支持,所以你可以直接像下面这样声明上面的函数:

这和C并没有什么不同。

Decoding bytes to text(将二进制转化为文本)

The initially presented way of passing and receiving C strings is sufficient if your code only deals with binary data in the strings. When we deal with encoded text, however, it is best practice to decode the C byte strings to Python Unicode strings on reception, and to encode Python Unicode strings to C byte strings on the way out.

初始的传递和接收C字符串的呈现方式已经足够了如果你的代码仅仅处理二进制字符串。当我们处理编码文本的时候,最好的做法是在接收时把C的字节字符串解码为Python的unicode字符串,然后在快结束的时候把Python的unicode字符串转化为C字节字符串。

With a Python byte string object, you would normally just call the  method to decode it into a Unicode string:

有一个Python的字节字符串对象,你正常将调用bytes.decode()方法来把它解码为Unicode字符串:

ustring = byte_string.decode('UTF-8&#​39;)

Cython allows you to do the same for a C string, as long as it contains no null bytes:

Cython允许你对C字符串做同样的事情,只要它没有包含null bytes。

And, more efficiently, for strings where the length is known:

更高效地是,对于长度已知的字符串:

The same should be used when the string contains null bytes, e.g. when it uses an encoding like UCS-4, where each character is encoded in four bytes most of which tend to be 0.

当包含空字节的时候,也需要用同样的操作,例如,当使用类似与UCS-4的编码方式的时候,这里每一个字符都以四个字节编码,很多字节都会是0。

Again, no bounds checking is done if slice indices are provided, so incorrect indices lead to data corruption and crashes. However, using negative indices is possible and will inject a call to in order to determine the string length. Obviously, this only works for 0-terminated strings without internal null bytes. Text encoded in UTF-8 or one of the ISO-8859 encodings is usually a good candidate. If in doubt, it’s better to pass indices that are ‘obviously’ correct than to rely on the data to be as expected.

如果提供了切片索引,就不做边界检查了 ,所以不正确的索引会导致数据损坏和崩溃。然而,使用负索引是可能的 ,为了得到字符串的长度会包含一个strlen。很明显,这只对于以、0作为终止符而没有内部0字节的字符串有效。使用UTF-8或者ISO-8859中的一种编码的文本是可以的。如果不确定,那么传递明显对的索引是比依赖于希望的数据更加好。

It is common practice to wrap string conversions (and non-trivial type conversions in general) in dedicated functions, as this needs to be done in exactly the same way whenever receiving text from C. This could look as follows:

在专门用途的函数中封装字符转换(有意义的普通类型转换)是普遍的操作,因为无论在什么时间接收到C的字符串,都需要做这一步。这可能看起来像下面:

Most likely, you will prefer shorter function names in your code based on the kind of string being handled. Different types of content often imply different ways of handling them on reception. To make the code more readable and to anticipate future changes, it is good practice to use separate conversion functions for different types of strings.

更有可能的是,你会更喜欢基于被处理字符串类型的更短的函数名在代码里。不同的语境类型经常有不同的处理方式。为了使得代码更加合理和预期未来的改变,对于不同类型的字符串使用不同的转换函数是一种良好的做法。

Encoding text to bytes(将文本编码为bytes)

The reverse way, converting a Python unicode string to a C , is pretty efficient by itself, assuming that what you actually want is a memory managed byte string:

相反的方式,将一个Python unicode字符串转化为一个C的char *是很高效的,假设你实际想要的是一个内存管理的byte string:

py_byte_string = py_unicode_string.encode('UTF-8&#​39;)

cdef char* c_string = py_byte_string

前面也猜测过,如果是ASCII码范围内的,bytes不会显示\x的十六进制而是显示原字符而超出范围的就需要显示十六进制。

As noted before, this takes the pointer to the byte buffer of the Python byte string. Trying to do the same without keeping a reference to the Python byte string will fail with a compile error:

以前也提到过,这使得指针指向Python byte字符串的byte存储区。尝试做同样的是而没有保持一个Python byte字符串的引用将会以一个编译错误而失败。

# this will not compile !

cdef char* c_string = py_unicode_string.encode('UTF-8&#​39;)

这时候会出现:

Here, the Cython compiler notices that the code takes a pointer to a temporary string result that will be garbage collected after the assignment. Later access to the invalidated pointer will read invalid memory and likely result in a segfault. Cython will therefore refuse to compile this code.

这里,Cython编译器注意到代码含有一个指向临时字符串的指针,导致在赋值之后就会被垃圾回收机制回收。之后到无效指针的访问会读取无效的内存并且会导致一个段错误。因此Cython会拒绝编译代码。

C++ strings

When wrapping a C++ library, strings will usually come in the form of the std::string class. As with C strings, Python byte strings automatically coerce from and to C++ strings:

当封装一个C++库的时候,字符串通常会是以std:string类的形式。和C字符串一样,Python的byte字符串自动转化为C++字符串从C++字符串转化。

The memory management situation is different than in C because the creation of a C++ string makes an independent copy of the string buffer which the string object then owns. It is therefore possible to convert temporarily created Python objects directly into C++ strings. A common way to make use of this is when encoding a Python unicode string into a C++ string:

内存管理的特点和在C里面不一样,因为创建一个C++字符串会创建一个字符串存储的独立副本,这里面存储字符串。因此把一个临时创建的Python对象直接转换到C++字符串是可以的。利用这一点的通常方式是当编码一个Python unicode字符串到一个c++字符串的时候:

cdef string cpp_string = py_unicode_string.encode('UTF-8&#​39;)

Note that this involves a bit of overhead because it first encodes the Unicode string into a temporarily created Python bytes object and then copies its buffer into a new C++ string.

注意这包含了一些开销,因为它首先把一个unicode字符串解码为一个临时创建的Python bytes对象然后把它的存储拷贝到一个新的C++字符串里面。

For the other direction, efficient decoding support is available in Cython 0.17 and later:

另一方面,高效的解码支持已经在Cython0.17及以后的版本可用了。

For C++ strings, decoding slices will always take the proper length of the string into account and apply Python slicing semantics (e.g. return empty strings for out-of-bounds indices).

对于C++的字符串,解码切片经常会考虑字符串合适的长度然后应用Python的切片语义(例如返回空的字符串如果索引越界)。

[2:-2]就是从左边第三个开始到右边到数第二个(不包含右边)。

Auto encoding and decoding(自动编码和解码)

Cython 0.19 comes with two new directives:  and . They can be used to change the Python string types that C/C++ strings coerce from and to. By default, they only coerce from and to the bytes type, and encoding or decoding must be done explicitly, as described above.

Cython0.19有两个指令:c_string_type和c_string_encoding。他们可以用来改变Python字符串的字符串类型,无论是从C/C++到Python还是反过来都是。默认的,唯一的从bytes类型到bytes类型的强制转换以及编码和解码都必须明确,就像上面形容的一样。

There are two use cases where this is inconvenient. First, if all C strings that are being processed (or the large majority) contain text, automatic encoding and decoding from and to Python unicode objects can reduce the code overhead a little. In this case, you can set the  directive in your module to  and the  to the encoding that your C code uses, for example:

有两个不方便使用的场景,首先是,如果所有的将要被处理C字符串(或者大部分)包含的文本,自动地从Python的unicode对象编码和解码可以减少一点代码的开销。在这种情况下,你可以在模块里设置c_string_type指令为unicode然后c_string_encoding为你C代码使用的编码。例如:

The second use case is when all C strings that are being processed only contain ASCII encodable characters (e.g. numbers) and you want your code to use the native legacy string type in Python 2 for them, instead of always using Unicode. In this case, you can set the string type to :

第二种使用场景是当所有的将被处理的字符串只包含ASCII码字符(例如数字)以及你想你的代码使用的Python2的遗留字符,而不是总是使用unicode。在这种场景下,你可以设置你的字符串类型为str: