字符串
- 字符串的表示
可以通过几种不同的方式表示字符串。如单引号('...')
或双引号("...")
。
>>> s = "I am Chinese"
>>> s
'I am Chinese'
>>> s = 'I am Chinese'
>>> s = "Here is a line \
... split in two lines"
>>> s
'Here is a line split in two lines'
>>> s = "Here is a line \n split in two lines"
>>> s
'Here is a line \n split in two lines'
>>> print(s)
Here is a line
split in two lines
要分几行输入字符串,并且希望行尾的换行符自动包含到字符串当中,可以使用三对引号:"""..."""
或 '''...'''
。
>>> print("""\
... Usage: thingy [OPTIONS]
... -h Display this usage message
... -H hostname Hostname to connect to
... """)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
- 方法
>>> s = "shi yan lou"
>>> s.title()
'Shi Yan Lou'
>>> z = s.upper()
>>> z
'SHI YAN LOU'
>>> z.lower()
'shi yan lou'
>>> s = "I am A pRoGraMMer"
>> s.swapcase()
'i AM a PrOgRAmmER'
>>> s = "I am A pRoGraMMer"
>> s.swapcase()
'i AM a PrOgRAmmER'
#方法 isalnum() 检查所有字符是否只有字母和数字
>>> s = "SankarshanSir"
>>> s.isalpha()
True
>>> s = "Sankarshan Sir"
>>> s.isalpha()
False
方法 isalpha() 检查字符串之中是否只有字母。
>>> s = "1234"
>>> s.isdigit() # 检查字符串是否所有字符为数字
True
>>> s = "ShiYanLou is coming"
>>> s.islower() # 检查字符串是否所有字符为小写
False
>>> s = "Shiyanlou Is Coming"
>>> s.istitle() # To 检查字符串是否为标题样式
True
>>> s = "CHINA"
>>> s.isupper() # 检查字符串是否所有字符为大写
True
>>> s = "We all love Python"
>>> s.split()
['We', 'all', 'love', 'Python']
>>> x = "shiyanlou:is:waiting"
>>> x.split(':')
['shiyanlou', 'is', 'waiting']
#使用 split() 分割任意字符串,split() 允许有一个参数,用来指定字符串以什么字符分隔(默认为 " "),它返回一个包含所有分割后的字符串的列表
>>> "-".join("GNU/Linux is great".split())
'GNU/Linux-is-great'
#方法 join() 使用指定字符连接多个字符串,它需要一个包含字符串元素的列表作为输入然后连接列表内的字符串元素。
#面的例子中,我们基于空格 " " 分割字符串 "GNU/Linux is great",然后用 "-" 连接它们。
- 字符串剥离
strip(chars):用来剥离字符串首尾中指定的字符,它允许有一个字符串参数,这个参数为剥离哪些字符提供依据。不指定参数则默认剥离掉首尾的空格和换行符。
>>> s = " a bc\n "
>>> s.strip()
'a bc'
lstrip(chars) 或 rstrip(chars) :只对字符串左或右剥离。
>>> s = "www.foss.in"
>>> s.lstrip("cwsd.") #删除在字符串左边出现的'c','w','s','d','.'字符
'foss.in'
>>> s.rstrip("cnwdi.") #删除在字符串右边出现的'c','n','w','d','i','.'字符
'www.foss'
- 文本搜索
>>> s = "faulty for a reason"
>>> s.find("for")
7
>>> s.find("fora")
-1
>>> s.startswith("fa") # 检查字符串是否以 fa 开头
True
>>> s.endswith("reason") # 检查字符串是否以 reason 结尾
True
#回文检查:回文是一种无论从左还是从右读都一样的字符序列。比如 “madam”。
#!/usr/bin/env python3
s = input("Please enter a string: ")
z = s[::-1] #把输入的字符串s 进行倒序处理形成新的字符串z
if s == z:
print("The string is a palindrome")
else:
print("The string is not a palindrome")
- 单词计数
格式化操作符(%):
print("my name is %s.I am %d years old" % ('zhangsan',4))
%s 为第一个格式符,表示一个字符串;%d 为第二个格式符,表示一个整数。格式符为真实值预留位置,并控制显示的格式。常用的有:
%s 字符串(用 str() 函数进行字符串转换)
%r 字符串(用 repr() 函数进行字符串转换)
%d 十进制整数
%f 浮点数
%% 字符“%”
单词计数
#!/usr/bin/env python3
s = input("Enter a line: ")
print("The number of words in the line are %d" % (len(s.split(" "))))
函数
- 函数定义
使用关键字 def 来定义一个函数:
def 函数名(参数):
语句1
语句2
>>> def sum(a, b):
... return a + b
#调用:
>>> res = sum(234234, 34453546464)
>>> res
34453780698L
一个栗子(回文检查程序):
#!/usr/bin/env python3
def palindrome(s):
return s == s[::-1]
if __name__ == '__main__':
s = input("Enter a string: ")
if palindrome(s):
print("Yay a palindrome")
else:
print("Oh no, not a palindrome")
- 局部变量、全局变量
#!/usr/bin/env python3
def change():
a = 90
print(a)
a = 9
print("Before the function call ", a)
print("inside change function", end=' ')
change()
print("After the function call ", a)
首先对 a
赋值 9,然后调用更改函数,这个函数里我们对 a
赋值 90,然后打印 a
的值。调用函数后我们再次打印 a
的值。
当我们在函数里写 a = 90
时,它实际上创建了一个新的名为 a
的局部变量,这个变量只在函数里可用,并且会在函数完成时销毁。所以即使这两个变量的名字都相同,但事实上他们并不是同一个变量。
那么如果先定义 a,在函数中是否可以直接使用呢?
#!/usr/bin/env python3
a = 9
def change():
print(a)
change()
这段代码是没有问题的,可以直接打印输出 9。但是:
#!/usr/bin/env python3
a = 9
def change():
print(a)
a = 100
change()
现在就会报错了:“UnboundLocalError: local variable ‘a’ referenced before assignment”,原因是当函数中只要用到了变量 a
,并且 a
出现在表达式等于号的前面,就会被当作局部变量。当执行到 print(a)
的时候会报错,因为 a
作为函数局部变量是在 print(a)
之后才定义的。
使用 global
关键字,对函数中的 a
标志为全局变量,让函数内部使用全局变量的 a
,那么整个程序中出现的 a
都将是这个:
#!/usr/bin/env python3
a = 9
def change():
global a
print(a)
a = 100
print("Before the function call ", a)
print("inside change function", end=' ')
change()
print("After the function call ", a)
程序中的 end=' '
参数表示,print 打印后的结尾不用换行,而用空格。默认情况下 print 打印后会在结尾换行。
程序执行的结果,不会报错了,因为函数体内可以访问全局的变量 a
:
Before the function call 9
inside change function 9
After the function call 100
- 默认参数值
函数的参数变量可以有默认值,也就是说如果我们对指定的参数变量没有给出任何值则会赋其默认值。
>>> def test(a , b=-99):
... if a > b:
... return True
... else:
... return False
在上面的例子里,我们在函数的参数列表写出 b = -99
。这表示如果调用者未给出 b 的值,那么 b 的值默认为 -99。这是一个关于默认参数的非常简单的例子。
>>> test(12, 23)
False
>>> test(12)
True
具有默认值的参数后面不能再有普通参数,比如 f(a,b=90,c)
就是错误的。
默认值只被赋值一次,因此如果默认值是任何可变对象时会有所不同,比如列表、字典或大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
>>> def f(a, data=[]):
... data.append(a)
... return data
...
>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]
要避免这个问题,你可以像下面这样:
>>> def f(a, data=None):
... if data is None:
... data = []
... data.append(a)
... return data
...
>>> print(f(1))
[1]
>>> print(f(2))
[2]
- 关键字参数
函数可以通过关键字参数的形式来调用,形如keyword = value
。如下:
>>> def func(a, b=5, c=10):
... print('a is', a, 'and b is', b, 'and c is', c)
...
>>> func(12, 24)
a is 12 and b is 24 and c is 10
>>> func(12, c = 24)
a is 12 and b is 5 and c is 24
>>> func(b=12, c = 24, a = -1)
a is -1 and b is 12 and c is 24
- 强制关键字参数
也能将函数的参数标记为只允许使用关键字参数。用户调用函数时将只能对每一个参数使用相应的关键字参数。
>>> def hello(*, name='User'):
... print("Hello", name)
...
>>> hello('shiyanlou')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() takes 0 positional arguments but 1 was given
>>> hello(name='shiyanlou')
Hello shiyanlou
6、文档字符串
使用文档字符串(docstrings)来说明如何使用代码:
#!/usr/bin/env python3
import math
def longest_side(a, b):
"""
Function to find the length of the longest side of a right triangle.
:arg a: Side a of the triangle
:arg b: Side b of the triangle
:return: Length of the longest side c as float
"""
return math.sqrt(a*a + b*b)
if __name__ == '__main__':
print(longest_side.__doc__)
print(longest_side(4,5))
7、高阶函数
高阶函数(Higher-order function)或仿函数(functor)是可以接受函数作为参数的函数,使用一个或多个函数作为参数,返回另一个函数作为输出:
# 创建一个函数,将参数列表中每个元素都变成全大写
>>> def h(l):
... return [i.upper() for i in l]
...
# 创建高阶函数,接受一个函数和一个列表作为参数
>>> def test(h, l):
... return h(l)
...
>>> l = ['python', 'Linux', 'Git']
# 运行高阶函数,返回预期的结果
>>> test(high, l)
['PYTHON', 'LINUX', 'GIT']
map函数—一个在 Python 里非常有用的高阶函数。它接受一个函数和一个序列(迭代器)作为输入,然后对序列(迭代器)的每一个值应用这个函数,返回一个序列(迭代器),其包含应用函数后的结果。
>>> lst = [1, 2, 3, 4, 5]
>>> def square(num):
... "返回所给数字的平方."
... return num * num
...
>>> print(list(map(square, lst)))
[1, 4, 9, 16, 25]
文件处理
文件是保存在计算机存储设备上的一些信息或数据。我们已经知道了一些不同的文件类型,比如音乐文件,视频文件,文本文件。Python 给了一些简单的方式操纵文件。通常我们把文件分为两类,文本文件和二进制文件。文本文件是简单的文本,二进制文件包含了只有计算机可读的二进制数据。
一、文件操作
1、文件打开
使用 open()
函数打开文件。它需要两个参数,第一个参数是文件路径或文件名,第二个是文件的打开模式。
模式通常是:
"r"
,以只读模式打开,只能读取文件但不能编辑/删除文件的任何内容;"w"
,以写入模式打开,如果文件存在将会删除里面的所有内容,然后打开这个文件进行写入;"a"
,以追加模式打开,写入到文件中的任何数据将自动添加到末尾;
默认的模式为只读模式,也就是说如果你不提供任何模式,open()
函数将会以只读模式打开文件。
>>> fobj = open("sample.txt")
>>> fobj
<_io.TextIOWrapper name='sample.txt' mode='r' encoding='UTF-8'>
2、文件关闭
使用方法 close()
完成
>>> fobj.close()
3、文件读取
使用 read()
方法一次性读取整个文件:
>>> fobj = open("sample.txt")
>>> fobj.read()
'I love Python\nI love shiyanlou\n'
>>> fobj.close()
如果再一次调用 read()
,它会返回空字符串因为它已经读取完整个文件。
read(size)
有一个可选的参数 size
,用于指定字符串长度。如果没有指定 size
或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。反之,会尽可能按比较大的 size
读取和返回数据。
readline() 能每次读取文件的一行:
>>> fobj = open("sample.txt")
>>> fobj.readline()
'I love Python\n'
>>> fobj.readline()
'I love shiyanlou\n'
>>> fobj.close()
可以循环遍历文件对象来读取文件中的每一行:
>>> fobj = open('sample.txt')
>>> for x in fobj:
... print(x, end = '')
...
I love Python
I love shiyanlou
>>> fobj.close()
让我们写一个程序,这个程序接受用户输入的字符串作为将要读取的文件的文件名,并且在屏幕上打印文件内容:
#!/usr/bin/env python3
name = input("Enter the file name: ")
fobj = open(name)
print(fobj.read())
fobj.close()
4、文件写入
通过 write()
方法打开一个文件然后我们随便写入一些文本:
>>> fobj = open("ircnicks.txt", 'w')
>>> fobj.write('powerpork\n')
>>> fobj.write('indrag\n')
>>> fobj.write('mishti\n')
>>> fobj.write('sankarshan')
>>> fobj.close()
>>> fobj = open('ircnicks.txt')
>>> s = fobj.read()
>>> fobj.close()
>>> print(s)
powerpork
indrag
mishti
sankarshan
5、拷贝文件
拷贝给定的文本文件到另一个给定的文本文件:
#!/usr/bin/env python3
import sys
if len(sys.argv) < 3:
print("Wrong parameter")
print("./copyfile.py file1 file2")
sys.exit(1)
f1 = open(sys.argv[1])
s = f1.read()
f1.close()
f2 = open(sys.argv[2], 'w')
f2.write(s)
f2.close()
在这里使用了一个新模块 sys
。sys.argv
包含所有命令行参数。这个程序的功能完全可以使用 shell 的 cp
命令替代:在 cp
后首先输入被拷贝的文件的文件名,然后输入新文件名。
sys.argv
的第一个值是命令自身的名字,下面这个程序打印命令行参数:
#!/usr/bin/env python3
import sys
print("First value", sys.argv[0])
print("All values")
for i, x in enumerate(sys.argv):
print(i, x)
运行结果:
$ ./argvtest.py Hi there
First value ./argvtest.py
All values
0 ./argvtest.py
1 Hi
2 there
这里用到了一个新函数 enumerate(iterableobject)
,在序列中循环时,索引位置和对应值可以使用它同时得到。
6、文本文件相关信息统计
试着编写一个程序,对任意给定文本文件中的制表符、行、空格进行计数:
(代码写入文件 /home/user/parsefile.py:)
#!/usr/bin/env python3
import os
import sys
def parse_file(path):
"""
分析给定文本文件,返回其空格、制表符、行的相关信息
:arg path: 要分析的文本文件的路径
:return: 包含空格数、制表符数、行数的元组
"""
fd = open(path)
i = 0
spaces = 0
tabs = 0
for i,line in enumerate(fd):
spaces += line.count(' ')
tabs += line.count('\t')
# 现在关闭打开的文件
fd.close()
# 以元组形式返回结果
return spaces, tabs, i + 1
def main(path):
"""
函数用于打印文件分析结果
:arg path: 要分析的文本文件的路径
:return: 若文件存在则为 True,否则 False
"""
if os.path.exists(path):
spaces, tabs, lines = parse_file(path)
print("Spaces {}. tabs {}. lines {}".format(spaces, tabs, lines))
return True
else:
return False
if __name__ == '__main__':
if len(sys.argv) > 1:
main(sys.argv[1])
else:
sys.exit(-1)
sys.exit(0)
运行结果:
$ ./parsefile.py sample.txt
Spaces 4. tabs 0. lines 2
可以看到程序有两个函数,main()
和 parse_file()
,parse_file()
函数真正的分析文件并返回结果,然后在 main()
函数里打印结果。
通过分割代码到一些更小的单元(函数)里,能帮助我们组织代码库并且也更容易为函数编写测试用例。
二、使用with语句
在实际情况中,我们应该尝试使用 with
语句处理文件对象,它会在文件用完后会自动关闭,就算发生异常也没关系。它是 try-finally 块的简写:
>>> with open('sample.txt') as fobj:
... for line in fobj:
... print(line, end = '')
...
I love Python
I love shiyanlou
三、字符串操作栗子
实现一个程序用来提取文件中的字符串中的数字,然后打印输出:
# 打开并读取文件里的字符串
with open('/tmp/String.txt') as f:
s = f.read()
res = ""
# 循环字符串里的每个字符,判断是否为数字
for char in s:
if char.isdigit():
res += char
print(res)
来源:实验楼