Windows 10家庭中文版,Python 3.6.4,
Python 3.7官文:
string — Common string operations
str類型
Python(特指Python 3)中包含字符串,字符串的類型為str,字符串是Unicode碼點(Unicode code codepoint)的序列,屬於不可變類型。
字符串有三種寫法:
單引號(Single quotes)、雙引號(Double quotes)、三引號(Triple quoted)。
單雙引號可以互相嵌套,三引號可以嵌套單雙引號,使得字符串擴展為多行。若要嵌套自身,需要用反斜杠轉移。
還可以使用str構造函數創建字符串:
class str(object='')
class str(object=b'', encoding='utf-8', errors='strict')
注意,第二個構造函數是基於bytes(准確的說法是 a bytes-like object (e.g. bytes or bytearray))構造字符串,也即實現bytes轉字符串的功能,但是要寫對encoding參數。
注意,str(bytes, encoding, errors)和bytes.decode(encoding, errors)功能相同。
新:
兩個字符串字面量之間只有空格時,它們會被自動轉換為一個字符串字面量。
>>> "sdfs" "www"
'sdfswww'
>>> ("sdfs" "www")
'sdfswww'
>>> "sdfs" "www" # 多個空格
'sdfswww'
參考:字符串字面量的語法 (有些復雜,不是一眼就可以看懂的,進階的話可以dig,此處略過)
字符串是不可變的,但是,可以使用str.join()方法創造字符串,或者使用io模塊的io.StringIO函數構造字符串,兩者原型如下:
str.join(iterable)
class io.StringIO(initial_value='', newline='\n')
后者還需要dig,前者略懂一二。
自己一直以來沒有搞明白字符串前面添加 r、u 做什么?現在OK了:
-r 表示字符串中所有的字符表示其本身,比如,反斜杠就是反斜杠,不是用來轉義的,'\n' 表示換行符,是一個字符,而 r'\n' 則是兩個字符——一個反斜杠、一個小寫n。
-u 表示字符串是Unicode字符串,在Python 3中保留是為了兼容Python 2,而Python 3中的字符串默認都是Unicode字符串,在Python 3中,不需要添加,而且不能和 r 一起使用。
repr()函數的用法:什么時候用?不是很清楚~菜鳥教程中的解釋:repr() 函數將對象轉化為供解釋器讀取的形式——使用eval()。
下面是一些測試:
>>> x = 'n'
>>> y = '\n'
>>> d1 = 123
>>> f1 = 999.87
>>> repr(x), repr(y), repr(d1), repr(f1)
("'n'", "'\\n'", '123', '999.87')
>>> len(repr(x)), len(repr(y)), len(repr(d1)), len(repr(f1))
(3, 4, 3, 6)
>>> eval(repr(x)), eval(repr(y)), eval(repr(d1)), eval(repr(f1))
('n', '\n', 123, 999.87)
Python字符串的 對象屬性、方法——使用dir(str)可以看到全部方法(methods,外部可以直接調用的有44個):
>>> for attr in dir(str):
print(attr, type(eval('str.%s' % attr)))
__add__ <class 'wrapper_descriptor'>
__class__ <class 'type'>
__contains__ <class 'wrapper_descriptor'>
__delattr__ <class 'wrapper_descriptor'>
__dir__ <class 'method_descriptor'>
__doc__ <class 'str'>
__eq__ <class 'wrapper_descriptor'>
__format__ <class 'method_descriptor'>
__ge__ <class 'wrapper_descriptor'>
__getattribute__ <class 'wrapper_descriptor'>
__getitem__ <class 'wrapper_descriptor'>
__getnewargs__ <class 'method_descriptor'>
__gt__ <class 'wrapper_descriptor'>
__hash__ <class 'wrapper_descriptor'>
__init__ <class 'wrapper_descriptor'>
__init_subclass__ <class 'builtin_function_or_method'>
__iter__ <class 'wrapper_descriptor'>
__le__ <class 'wrapper_descriptor'>
__len__ <class 'wrapper_descriptor'>
__lt__ <class 'wrapper_descriptor'>
__mod__ <class 'wrapper_descriptor'>
__mul__ <class 'wrapper_descriptor'>
__ne__ <class 'wrapper_descriptor'>
__new__ <class 'builtin_function_or_method'>
__reduce__ <class 'method_descriptor'>
__reduce_ex__ <class 'method_descriptor'>
__repr__ <class 'wrapper_descriptor'>
__rmod__ <class 'wrapper_descriptor'>
__rmul__ <class 'wrapper_descriptor'>
__setattr__ <class 'wrapper_descriptor'>
__sizeof__ <class 'method_descriptor'>
__str__ <class 'wrapper_descriptor'>
__subclasshook__ <class 'builtin_function_or_method'>
capitalize <class 'method_descriptor'>
casefold <class 'method_descriptor'>
center <class 'method_descriptor'>
count <class 'method_descriptor'>
encode <class 'method_descriptor'>
endswith <class 'method_descriptor'>
expandtabs <class 'method_descriptor'>
find <class 'method_descriptor'>
format <class 'method_descriptor'>
format_map <class 'method_descriptor'>
index <class 'method_descriptor'>
isalnum <class 'method_descriptor'>
isalpha <class 'method_descriptor'>
isdecimal <class 'method_descriptor'>
isdigit <class 'method_descriptor'>
isidentifier <class 'method_descriptor'>
islower <class 'method_descriptor'>
isnumeric <class 'method_descriptor'>
isprintable <class 'method_descriptor'>
isspace <class 'method_descriptor'>
istitle <class 'method_descriptor'>
isupper <class 'method_descriptor'>
join <class 'method_descriptor'>
ljust <class 'method_descriptor'>
lower <class 'method_descriptor'>
lstrip <class 'method_descriptor'>
maketrans <class 'builtin_function_or_method'>
partition <class 'method_descriptor'>
replace <class 'method_descriptor'>
rfind <class 'method_descriptor'>
rindex <class 'method_descriptor'>
rjust <class 'method_descriptor'>
rpartition <class 'method_descriptor'>
rsplit <class 'method_descriptor'>
rstrip <class 'method_descriptor'>
split <class 'method_descriptor'>
splitlines <class 'method_descriptor'>
startswith <class 'method_descriptor'>
strip <class 'method_descriptor'>
swapcase <class 'method_descriptor'>
title <class 'method_descriptor'>
translate <class 'method_descriptor'>
upper <class 'method_descriptor'>
zfill <class 'method_descriptor'>
'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'
包括查找、去除左右空格、判斷字符串元素的類別、分隔——中文分隔需要用re模塊、大小寫轉換、轉換為bytes——encode、格式化字符串——本文后面會簡單介紹、居中、左右對齊、替換replace等。
string模塊
string模塊包含了一些字符串常量,另外還有Formatter類、Template類和一個幫助函數capwords(string.capwords(s, sep=None))。
其中,Formatter類型 用於字符串格式化,繼承它可以開發自定義的格式化類;Template類 提供簡單的字符串替換功能,主要用途是上下文的國際化(internationalization (i18n))。
字符串常量包括——感覺用處不是很大:
string.ascii_letters string.ascii_lowercase string.ascii_uppercase string.digits string.hexdigits string.octdigits string.punctuation string.printable string.whitespace
下面是測試,可是,發生了錯誤,和上面講的一條規則沖突了——沒有連接起來:
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.ascii_letters string.digits
SyntaxError: invalid syntax
>>> '2323' 'sdsds'
'2323sdsds'
>>>
>>> type(string.digits)
<class 'str'>
>>> type(string.ascii_letters)
<class 'str'>
學習筆記:
學習了一遍str、string,發現string幾乎很難用到,字符串類型的大部分功能都在str類型中,除了Template類的使用,當然,這個也可以使用str本身的格式化功能實現,當然,Template會更便捷——語法相對來說較為簡單。
關於Formatter類,string模塊官文說它和str.format()函數進行格式化轉換時使用的是相同的語法,但是,開發者可以繼承Formatter類實現自己特有的格式化字符串功能——絕大部分開發者用不到吧?兩者的語法都是和Formatted string literals相關,但又有不同之處——請查看官文。
字符串格式化簡介
經過前面的學習,發現Python字符串有4種格式化的語法:
1.printf-style String Formatting
format % values
2.the newer formatted string literals
A formatted string literal or f-string is a string literal that is prefixed with 'f' or 'F'.
解釋:在字符串字面量前面添加 f or F,即可使用當前命名空間中的元素來格式化字符串了,不需要像其它語法一樣把格式化字符串和變量放在一起,,的確有些高級呢!
使用示例:
>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}." # repr() is equivalent to !r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}" # using date format specifier
'January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}" # using integer format specifier
'0x400'
3.the str.format() interface / string.Formatter
str.format(*args, **kwargs)
str.format_map(mapping) 和 str.format(**mapping) 功能相同(相似,原文:Similar to str.format(**mapping), except that mapping is used directly and not copied to a dict.)
示例:
>>> "The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'
>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c') # 3.1+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc') # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad') # arguments' indices can be repeated
'abracadabra'
>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> 'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'
更多示例請查看string模塊下的Format Examples,有不少高級或更復雜的用法,適合進階使用。
支持使用美元符號$來做替換,$identifier、${identifier}兩種替換方式,兩個美元符號($$)為轉義,代表一個美元符號$。的確挺簡單的。
class string.Template(template)
-substitute(mapping, **kwds)
-safe_substitute(mapping, **kwds)
開發者可以繼承Template類,實現自定義的模板類。
官文使用示例:
>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
...
ValueError: Invalid placeholder in string: line 1, col 11
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
...
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'
學習筆記:
語法1類似於C語言的priintf函數的格式化字符串方法;
語法2請查看參考鏈接2,孤還沒有細讀;
語法3在str.format()函數和string模塊的Formatter類中使用,和語法2有關聯——基於語法2?;
語法4是string模塊提供的一種簡單的字符串替換功能。
都知道怎么使用了,基本的使用,但是,更有難度的是理解它們的語法,下面補充語法2、語法3的描述(官文,具體解釋也請查看官文),這兩個是最難的:
語法2:
f_string ::= (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::= "{" f_expression ["!" conversion] [":" format_spec] "}"
f_expression ::= (conditional_expression | "*" or_expr)
("," conditional_expression | "," "*" or_expr)* [","]
| yield_expression
conversion ::= "s" | "r" | "a"
format_spec ::= (literal_char | NULL | replacement_field)*
literal_char ::= <any code point except "{", "}" or NULL>
語法3:
format_spec ::= [[fill]align][sign][#][0][width][grouping_option][.precision][type] fill ::= <any character> align ::= "<" | ">" | "=" | "^" sign ::= "+" | "-" | " " width ::= digit+ grouping_option ::= "_" | "," precision ::= digit+ type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
疑問:
這些人怎么想到使用上面的方式來表示語法呢?在計算機科學中,上面的結構叫做什么?好像自己在其它的文檔中也看到過,只是,不理解,歡迎讀者賜教!和編譯原理有關系嗎?能寫出上面語法的人一定很聰明吧,或者,在計算機科學上有很高的造詣!當然,很可能是站在某些計算機科學先驅的肩膀上,比如C語言的創造者們,當然,還可以繼續追溯。
本文就這樣吧,幾乎涵蓋了Python的str類型、string模塊的各個知識點,暫且交差。其中,str中的字符串函數還需要 重難點練習突破,格式化字符串還需要更多場景來練習突破(官文示例好好研究下)。
更進一步
在學習過程中發現,str.split函數在分隔漢語句子時失敗了,需要用re模塊的分隔函數,此問題以及中文的相關問題(中文分詞?中文詞雲?自然語言識別?)還需dig:
>>> cnstr = '姑娘還曬出了自己的辭職信,引發眾多網友關注。姑娘說,她在這家公司上班6年,一個月3.5k左右。在辭職信中,她列出了7條離職原因。沒想好做什么,但是不能繼續這樣下去了’'
>>> cnstr.split('了的')
['姑娘還曬出了自己的辭職信,引發眾多網友關注。姑娘說,她在這家公司上班6年,一個月3.5k左右。在辭職信中,她列出了7條離職原因。沒想好做什么,但是不能繼續這樣下去了’']
>>> len(cnstr.split('了的')) # 分隔失敗,返回列表長度為1
1
>>> import re
>>> re.split('[了的]', cnstr) # '[了的]' 是正則表達式
['姑娘還曬出', '自己', '辭職信,引發眾多網友關注。姑娘說,她在這家公司上班6年,一個月3.5k左右。在辭職信中,她列出', '7條離職原因。沒想好做什么,但是不能繼續這樣下去', '’']
參考鏈接
str.join(iterable)
