一,python3基础知识重点

1,浮点数

print(10 / 2)  #正如您之前看到的,两个整数相除将产生一个浮点数。
一个浮点数也是通过在两个浮点数或者在一个浮点数和一个整数上运算来产生的。
print(6 * 7.0)
print(5 + 2.32)
结果:
5.0
42.0
7.32

2,不可变对象

Python 中一切皆对象,每一个对象都有一个唯一的标示符(id())、类型(type())以及值。对象根据其值能否修改分为可变对象和不可变对象,其中数字字符串元组属于不可变对象,字典以及列表字节数组属于可变对象。而“菜鸟”常常会试图修改字符串中某个字符。看下面这个例子:

teststr = "I am a string"
teststr[11]='h'
print(teststr)

这样会报错 

如果要修改字符串, 可以重新给生成一个字符串,或者将字符串拆解成数组,修改完成后再合并成字符串

3,类型转换

在 Python 中,涉及到一些类型是不能完成某些操作的。

例如,您不能将包含数字2和3的两个字符串添加到一起以生成整数5,因为操作会将在字符串拼接为“23”。

解决方案是类型转换。 在这个例子中,你将使用 int 函数将字符串转成整数。

print("2" + "3")
print(int("2") + int("3"))
结果
23
5

另一个类型转换的例子是将用户输入(会自动转成一个字符串)转换为数字(整数或浮点数),以便进行计算。

>>> float(input("Enter a number: ")) + float(input("Enter another number: "))
Enter a number: 30
Enter another number: 2
32.0

4,python 中文编码

前面章节中我们已经学会了如何用 Python 输出 "Hello, World!",英文没有问题,

但是如果你输出中文字符"你好,亿动"就有可能会碰到中文编码问题。

解决方法很简单, 只要在文件开头加入 # -*- coding: UTF-8 -*- 或者 #coding=utf-8 就行了。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

print("你好,亿动")

5,布尔类型

Python 中的另一种类型是布尔类型。有两个布尔值:TrueFalse

可以通过比较值的方法来创建它们,例如通过使用相等的运算符 ==

>>> my_boolean = True
>>> my_boolean
True

>>> 2 == 3
False
>>> "hello Edong" == "hello Edong"
True
注意:
不要把赋值(一个等号)与比较(两个等号)混淆。
Python是区分大小写的,所以True与true是不同的。

6,while 循环

如果 if 语句的计算结果为 True,则 if 语句的代码块会运行一次,如果计算结果为 False,则不会运行。

while 语句是相似的,while 只要条件为True,while内部的代码块就会重复执行。

当条件为 False 时就停止 while 循环,程序继续往后执行。

i = 1
while i <=5:
   print(i)
   i = i + 1
print("Finished!")
while 循环体中的代码被重复执行。这被称为迭代。

break 语句

要提前结束 while 循环,可以使用 break 语句。

在循环中遇到时,break 语句会立即结束循环。

i = 0
while 1==1:
  print(i)
  i = i + 1
  if i >= 5:
    print("Breaking")
    break

print("Finished")
#在循环外部使用 break 语句会导致错误。

continue 语句

可以在循环内使用的另一个语句是 continue 语句。

与 break 不同的是,continue 语句是提前结束本次循环,进入下一次循环。

i = 0
while True:
   i = i +1
   if i == 2:
      print("Skipping 2")
      continue
   if i == 5:
      print("Breaking")
      break
   print(i)

print("Finished")
结果
1
Skipping 2
3
4
Breaking
Finished

简而言之:continue 语句停止当前的迭代,并继续下一个。

在循环外部使用 continue 语句会导致错误。

7,列表

列表是 Python 中的另一种类型的对象。它们被用来存储索引的元素列表。

方括号中用逗号分隔元素来创建一个列表。

列表中的某个元素可以通过使用方括号中的索引来访问。

例如:

words = ["Hello", "world", "!"]
print(words[0])
print(words[1])
print(words[2])

通常情况下,列表包含单种数据类型的元素,但也可以包含几个不同的类型。

列表也可以嵌套在其他列表中

number = 3
things = ["string", 0, [1, 2, number], 4.56]
print(things[1])
print(things[2])
print(things[2][2])
结果
0
[1, 2, 3]
3

列表操作

1,列表中某个索引处的元素值可以被重新分配。

例如

nums = [7, 7, 7, 7, 7]
nums[2] = 5
print(nums)
2,列表可以像字符串一样添加和相乘。
nums = [1, 2, 3]
print(nums + [4, 5, 6])
print(nums * 3)
结果
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 1, 2, 3, 1, 2, 3]

3,要查找某个值是否在列表中,可以使用 in 运算符。如果值在列表中出现一次或多次,则返回 True,否则返回 False

words = ["spam", "egg", "spam", "sausage"]
print("spam" in words)
print("egg" in words)
print("tomato" in words)
结果
True
True
False
4,要某个值是否不在列表中,可以使用 not 操作符:
nums = [1, 2, 3]
print(not 4 in nums)
print(4 not in nums)
print(not 3 in nums)
print(3 not in nums)
结果
True
True
False
False

列表函数

可以使用 append 方法将一个元素添加到现有列表的末尾。

nums = [1, 2, 3]
nums.append(4)
print(nums)  #结果:
[1, 2, 3, 4]

append 是列表类的一个方法。

要获取列表中的项目数量,可以使用 len 函数。

nums = [1, 3, 5, 2, 4]
print(len(nums))
结果:
5

与 append 方法不同,len 是一个正常的函数,而不是一个方法。这意味着它写在被调用的列表之前。

insert 方法与 append 相似,不同之处在于它允许您在列表中的任何位置插入一个新元素,而不仅仅是在最后。

words = ["W3Cschool", "Good"]
index = 1
words.insert(index, "is")
print(words)
结果:
['W3Cschool', 'is', 'Good']

index 方法找到列表项的第一个匹配项并返回它的索引。

如果该项目不在列表中,则会引发 ValueError

letters = ['p', 'q', 'r', 's', 'p', 'u']
print(letters.index('r'))
print(letters.index('p'))
print(letters.index('z'))
2
0
ValueError: 'z' is not in list

列表还有一些很有用的功能和方法。

max(list): 返回具有最大值的列表元素

min(list): 返回具有最小值的列表元素

list.count(obj): 返回一个元素在一个列表中出现的次数

list.remove(obj):从列表中删除一个元素

list.reverse():颠倒列表中的元素的顺序

8, 范围(range)

使用范围函数创建一个顺序的数字列表。

numbers = list(range(10))
print(numbers)
结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Range 本身会创建一个 Range 对象,所以调用 list 函数将其转换为列表。

如果使用一个参数调用 Range,则会生成0到该参数值的对象。

如果使用两个参数调用范围,则会从第一个值到第二个值的对象。

例如:

numbers = list(range(3, 8))
print(numbers)

print(range(20) == range(0, 20))
结果:
[3, 4, 5, 6, 7]

True

Range 可以有第三个参数,第三个参数决定了产生的序列的间隔。

numbers = list(range(5, 20, 2))
print(numbers)
结果:
[5, 7, 9, 11, 13, 15, 17, 19]

注意: 第三个参数必须是一个整数, 否则会报TypeError。

9,for 循环

使用 while 循环遍历列表需要相当多的代码,所以 Python 提供了 for 循环作为完成相同事情的快捷方式。

前一个例子中的代码可以用 for 循环来编写,如下所示:

words = ["hello", "world", "spam", "eggs"]
for word in words:
  print(word + "!")
  结果:
hello!
world!
spam!
eggs!

Python中的 for 循环就像其他语言的 foreach 循环一样。

for 循环通常用于重复某些代码一定次数。这是通过将循环与范围 range 对象结合来完成的。

for i in range(5):
  print("hello!")

在 for 循环中使用 range 对象时不需要调用 list,因为它没有被索引,所以不需要列表。

10,函数

除了使用预定义的函数外,还可以使用 def 语句创建自己的函数。

这是一个名为 my_func 的函数的例子。它不需要任何参数,并打印 "你好,Loen" 三次。先定义函数,然后被调用。

函数中的代码块仅在调用函数时执行。

def my_func():
   print("你好,Loen")
   print("你好,Loen")
   print("你好,Loen")
my_func();
结果:
你好,Loen
你好,Loen
你好,Loen

大部分函数都有参数。 下面的例子定义了一个带有一个参数的函数:

def print_with_exclamation(word):
   print(word + "!")
    
print_with_exclamation("皮卡丘")
print_with_exclamation("可达鸭")
print_with_exclamation("小火龙")
结果:
皮卡丘!
可达鸭!
小火龙!

正如你所看到的,参数是在括号内定义的。

使用逗号分隔多个参数

def print_sum_twice(x, y):
   print(x + y)
   print(x + y)

print_sum_twice(3, 8)  #相当于把用户输入的两个参数计算相加,然后输出,定义的参数不一样结果也不一样。
结果:
11
11

函数参数可以在函数内部当变量使用。但是,它们不能在函数的定义之外被引用。函数内部创建的其他变量也不能在函数外部被引用

def function(variable):
   variable += 1
   print(variable)

function(7)  #这个函数就是输出参数值+1
print(variable)  #外部引用会报错
结果:
8 
NameError: name 'variable' is not defined

11,函数返回值

某些函数(如 int 或 str)会返回一个稍后可用的值。 定义的函数可以使用 return 语句执行此操作。

例如:

def max(x, y):
    if x >=y:
        return x
    else:
        return y
        
print(max(4, 7))   #4不>= 7(y),所以返回else的内容7
z = max(8, 5)
print(z)  #条件成立,所以返回x(8)
结果:
7
8

return 语句不能在函数定义之外使用。

定义一个函数比较参数长度,并返回最短的一个。

def shortest_string(x, y):
    if len(x)<=len(y):
        return x
    else:
        return y
    
print(shortest_string("hallo","ni"))
结果:
ni

一旦你从一个函数返回一个值,函数立即停止执行。返回语句之后的任何代码都不会执行。

例如:

def add_numbers(x, y):
  total = x + y
  return total
  print("This won't be printed")  #这个就不会执行了

print(add_numbers(4, 5))  #返回9 
结果:
9 

函数与其他任何类型的值一样。可以将它们重新分配给变量,并在稍后由这些变量名称引用函数。

def multiply(x, y):
   return x * y

a = 4
b = 8
operation = multiply
print(operation(a, b)) #operation(a,b)等于 multiply(a,b)函数
结果:
32  

函数也可以做为其他函数的参数。(PS:建议大家自己打一遍,深刻感受加深理解)

def add(x,y):
    return x+y
    
def subtract(x,y):
    return x-y
    
def do_twice(func,x,y):
    return func(func(x,y),func(x,y)) 
    #func参数就变成了add函数了,变成了返回 func(func(5+10),func(5+10)) 等于func(15,15)等于 30

a = 5
b = 10
print(do_twice(add,a,b))

正如你所看到的,函数 do_twice 接收一个函数做为参数,并在它的函数内部调用它。

将函数“square”作为参数传递给函数“test”:

def square(x):
    return x*x  #返回42*42=1746

def test(func,x):  
    print(func(x))  #输出 func(42)等于输出square(42)
    
test(square,42)
结果:
1746

12, 模块

模块是其他人为完成常见任务而编写的一些代码,例如生成随机数字,执行数学运算等。

使用模块的基本方法是在代码顶部添加 import 模块名 。

使用 模块名.变量 或者 模块名.函数 访问模块中的变量和函数。

import random

for i in range(5):
   value = random.randint(1, 6)
   print(value)
   结果:
2
5
1
3
2
代码使用 radom 模块中定义的 randint 函数打印1到6范围内的5个随机数。

如果您只需要某个模块的某些功能,就可以使用另一种导入方式。

使用 from 模块名 import 变量名 的形式,然后变量名可以像在代码中正常定义一样使用。

from math import pi

print(pi)
结果:
3.141592653589793

可以使用逗号分隔导入多个对象。例如:

from math import pi, sqrt

可以使用 导入模块中所有对象。例如: from math import

注意: 通常不鼓励这样做,因为它会将代码中的变量与外部模块中的变量混淆。

您可以使用 as 关键字给导入的模块或对象重命名。模块或对象名称较长或容易混淆的时候比较常用。

例如:

from math import sqrt as square_root
print(square_root(100))
结果:
10.0

一些常用的标准库

string,re,datetime,math,random,os,multiprocessing,subprocess,socket,email,json,doctest,unittest,pdb,argparse, sys

标准库可以完成的任务包括字符串解析,数据序列化,测试,调试和操作日期,电子邮件,命令行参数等等。

许多第三方 Python 模块都存储在 Python Package Index(PyPI)中。

最好的安装方法是使用 pip 的程序。Python 的发行版默认安装了 pip。如果没有安装 pip,也可以很容易通过在线安装。

一旦拥有它,从 PyPI 安装库是很容易的。查找要安装的库的名称,转到命令行(对于Windows,是命令提示符),然后输入 pip install 模块名。完成此操作后,导入库并在代码中使用它。

使用 pip 是在大多数操作系统上安装库的标准方法,但是一些库已经为 Windows 预编译了二进制文件。这些是正常的可执行文件,可以让您使用 GUI 安装库,这与安装其他程序的方式相同。

13,异常

不同的异常是由不同的原因引起的。

常见的异常:

  • ImportError: 无法引入模块或包。
  • IndexError: 下标索引超出序列边界;
  • NameError: 使用一个还未赋予对象的变量;
  • SyntaxError: 代码逻辑语法出错,不能执行;
  • TypeError: 传入的对象类型与要求不符;
  • ValueError: 传入一个不被期望的值,即使类型正确。
  • KeyError: 试图访问你字典里不存在的键。
  • IOError: 输入输出异常。
Python还有其他一些内置的异常,比如 ZeroDivisionError 和 OSError 。

第三方库也经常定义自己的异常。

1,异常处理

为了处理异常,并在发生异常时调用代码,可以使用 try/except 语句。

try 块包含可能会引发异常的代码。如果发生该异常,try 块中的代码将停止执行,并且 except 块中的代码将被运行。如果没有错误发生,except 块中的代码不会运行。

例如:

try:
   num1 = 5
   num2 = 0
   print (num1 / num2)
   print("计算完成")
except ZeroDivisionError:
   print("发生错误")
   print("您尝试进行除0操作")

try 语句可以有多个不同的 except 块来处理不同的异常。除了使用圆括号的块外,还可以将多个异常放入一个单独的块中,使 except 块处理所有这些异常。

try:
   variable = 10
   print(variable + "hello")
   print(variable / 2)
except ZeroDivisionError:
   print("Divided by zero")
except (ValueError, TypeError):
   print("Error occurred")
   
结果: Error occurred   #匹配到了TypeError错误

没有指定任何异常的 except 语句将捕获所有错误。应该谨慎使用,因为他们可以捕捉到意想不到的错误并隐藏编程错误。

例如:

try:
   word = "spam"
   print(word / 0)
except:
   print("发生错误")
  结果:
  发生错误
   

在处理用户输入时,异常处理特别有用。

2,finally 语句

为了确保某些代码不管发生什么错误都运行,可以使用 finally 语句。finally 语句放置在 try/except 语句的底部。

finally 语句中的代码总是在 try 中的代码执行之后运行,可能在 except 代码块中运行。

try:
   print("Hello")
   print(1 / 0)
except ZeroDivisionError:
   print("Divided by zero")
finally:
   print("这段代码无论如何都会运行")
 结果:

Hello
Divided by zero
这段代码无论如何都会运行

如果在前面的一个块中发生未捕获的异常,也会运行 finally 语句中的代码。

3,引发异常(rause)

您可以使用 raise 语句引发异常。

print(1)
raise ValueError
print(2)   #这条就不会执行了
结果:
1
ValueError

您需要指定引发的异常的类型。

引发异常可以提供一些异常的描述。

name = "123"
raise NameError("Invalid name!")
结果:
NameError: Invalid name!

except 块下,raise 语句可以在没有参数的情况下使用来重新引发发生的异常。

try:
   num = 5 / 0
except:
   print("An error occurred")
   raise
  结果:
 An error occurred

ZeroDivisionError: division by zero

可以在 except 块外面使用 raise 语句

4,断言(assert)

使用 assert 断言是一个非常好的习惯,python assert 断言句语格式及用法很简单。在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要 assert 断言的帮助。

assert 断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假。可以理解 assert 断言语句为 raise-if-not,用来测试表示式,其返回值为假,就会触发异常。

断言是通过使用 assert 语句来执行的。

print(1)
assert 2 + 2 == 4
print(2)
assert 1 + 1 == 3  #这里出错,就不会输出下面的了
print(3)
结果:
1
2
AseertionError

程序员经常在函数的开始处放置断言来检查有效的输入,并且在函数调用之后检查有效的输出。

如果断言失败,assert 可以接受第二个传递给 AssertionError 的参数。

temp = -10
assert (temp >= 0), "Colder than absolute zero!"
结果:
AssertionError: Colder than absolute zero!

AssertionError 异常可以像使用 try-except 语句的任何其他异常一样被捕获和处理,但是如果不处理,这种类型的异常将终止程序。

15,文件操作

1,打开文件

您可以使用 Python 来读取和写入文件的内容。

文本文件是很容易操作的。在编辑文件之前,必须使用 open 函数打开文件。

myfile = open("filename.txt")

open 函数的参数是文件的路径。

如果文件与程序位于同一目录中,你可以直接使用文件名称。

您可以通过向 open 函数应用第二个参数来指定用于打开文件的模式。

参数 “r” 表示在读取模式下打开,这是默认设置。

参数“w”表示写入模式,用于重写文件的内容。

参数“a”表示追加模式,用于将新内容添加到文件末尾。

将“b”添加到某个模式中文件将以二进制模式打开它,该模式用于非文本文件(如图像和声音文件)。

例如:

# 写模式
open("filename.txt", "w")

# 读模式
open("filename.txt", "r")
open("filename.txt")

# 二进制写入模式
open("filename.txt", "wb")

文件被打开和使用后要记得关闭它。通过文件对象的 close 方法进行关闭。

file = open("filename.txt", "w")
# do stuff to the file
file.close()

2,读文件

可以使用 read 方法读取以文本模式打开的文件的内容。

file = open("filename.txt", "r")
cont = file.read()
print(cont)
file.close()

这将打印文件 “filename.txt” 的所有内容。

如果只要读取文件一部分内容,你可以提供一个数字作为 read 方法的参数。决定要读取的字节数。

你可以进行多次调用来读取同一个文件对象,逐字节读取更多的内容。如果没有参数,read 返回文件的其余部分内容。

file = open("filename.txt", "r")
print(file.read(16))
print(file.read(4))
print(file.read(4))
print(file.read())
file.close()

打开utf-8格式编码的文件

file = open("filename.txt", "r", encoding="UTF-8")

在读取完文件中的所有内容之后,如果试图从该文件进一步读取,将会返回一个空字符串,因为您正试图从文件末尾进行读取。

file = open("filename.txt", "r")
file.read()
print("Re-reading")
print(file.read())
print("Finished")
file.close()
结果:
Re-reading

Finished

要检索文件中的每一行,可以使用 readlines 方法返回一个列表,其中每个元素是文件中的一行。

例如:

demofile.txt

Line 1 text
Line 2 text
Line 3 text

demo.py

file = open("demofile.txt", "r")
print(file.readlines())
file.close()
结果:
['Line 1 text\n', 'Line 2 text\n', 'Line 3 text']

您也可以使用 for 循环遍历文件中的行:

file = open("demofile.txt", "r")

for line in file:
    print(line)

file.close() 
结果:
Line 1 text

Line 2 text

Line 3 text

在输出中,行由空行分隔,因为 print 函数在其输出结束时自动添加新行。

3,写文件

要写入文件,请使用 write 方法,该方法将字符串写入文件。

例如:

file = open("newfile.txt", "w")
file.write("This has been written to a file")
file.close()

file = open("newfile.txt", "r")
print(file.read())
file.close()
结果:
This has been written to a file

“w” 模式如果文件不存在,将创建一个文件。

如果写入成功的话 write 方法返回写入文件的字节数。

msg = "Hello world!"
file = open("newfile.txt", "w")
amount_written = file.write(msg)
print(amount_written)
file.close()
结果:
12

要确保文件在使用后始终关闭,避免浪费资源是一种好的做法。一个方法是使用 tryfinally

try:
   f = open("newfile.txt")
   print(f.read())
finally:
   print("即使发生错误,这可以确保文件始终关闭。")
   f.close()

一个替代方法是使用语句。这将创建一个临时变量(通常称为f),该变量只能在 with 语句的缩进块中访问。

with open("newfile.txt") as f:
   print(f.read())

在 with 语句结束时,即使文件内部发生异常,文件也会自动关闭。

16,字典

字典 是用于将任意键映射到值的数据结构。

列表可以被认为是在一定范围内具有整数键的字典。

字典可以用与列表相同的方式建立索引。

使用 字典["键名"] 可以获取对应的值。

例如:

ages = {"Dave": 24, "Mary": 42, "John": 58}
print(ages["Dave"])
print(ages["Mary"])
结果:
24
42

就像列表一样,字典键可以被分配到不同的值。

但是,与列表不同,新的字典键也可以被赋值,而不仅仅是已经存在的字典键。

例如:

squares = {1: 1, 2: 4, 3: "error", 4: 16,}
squares[8] = 64
squares[3] = 9
print(squares)
结果:
{8: 64, 1: 1, 2: 4, 3: 9, 4: 16}

要确定 key (键)是否在字典中,您可以使用 innot,就像你可以使用列表一样。

nums = {
  1: "one",
  2: "two",
  3: "three",
}
print(1 in nums)
print("three" in nums)
print(4 not in nums)
结果:
True
False
True

一个很有用的字典方法是 get 。它与索引做同样的事情,但是如果在字典中找不到键,它将返回另一个指定的值(默认情况下为“None”)。

例如:

pairs = {1: "apple",
  "orange": [2, 3, 4], 
  True: False, 
  None: "True",
}

print(pairs.get("orange"))
print(pairs.get(7))
print(pairs.get(12345, "not in dictionary"))
结果:
[2, 3, 4]
None
not in dictionary

17,元组

元组与列表非常相似,不过元组是不可变的

而且,它们使用圆括号创建,而不是方括号。

words = ("spam", "eggs", "sausages",)

你可以使用索引访问元组中的值,就像使用列表一样:

print(words[0])

尝试重新分配元组中的值会导致 TypeError。

words[1] = "cheese"

结果:

TypeError: 'tuple' object does not support item assignment

像列表和字典一样,元组也可以相互嵌套。

元组可以在没有括号的情况下创建,只需用逗号分隔值。

例如:

my_tuple = "one", "two", "three"
print(my_tuple[0])
结果:
one

元组比列表快,但是元组不能改变。

18,列表切片

列表切片(List slices)提供了从列表中检索值的更高级的方法。基本列表切片涉及用两个以冒号分隔的整数索引列表。

列表切片返回一个包含索引之间旧列表中所有值的新列表。

squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(squares[2:6])
print(squares[3:8])
print(squares[0:1])
结果:
[4, 9, 16, 25]
[9, 16, 25, 36, 49]
[0]

和Range参数一样,在一个 slice 中提供的第一个索引被包含在结果中,但是第二个索引没有。

如果省略了切片中的第一个数字,则将从列表第一个元素开始。

如果第二个数字被省略,则认为是到列表结束。

squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(squares[:7])
print(squares[7:])
结果:
[0, 1, 4, 9, 16, 25, 36]
[49, 64, 81]

切片也可以在元组上使用。

列表切片还可以有第三个数字,表示间隔。

squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(squares[::2])
print(squares[2:8:3])
结果:
[0, 4, 16, 36, 64]
[4, 25]

[2:8:3] 包含从索引2到8间隔3的元素。

负值也可用于列表切片(和正常列表索引)。当切片(或普通索引)中的第一个和第二个值使用负值时,它们将从列表的末尾算起。

squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(squares[1:-1])
print(squares[-3:-1])
print(squares[::-1])
结果:
[1, 4, 9, 16, 25, 36, 49, 64]
[49, 64]
[81, 64, 49, 36, 25, 16, 9, 4, 1, 0]

sqs = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print(sqs[7:5:-1])
[49, 36]

如果切片第三个数值使用负值,则切片进行逆序截取。
使用[::-1]作为切片是反转列表的常用方法。

19,字符串格式化

到目前为止,要组合字符串和非字符串,将非字符串转换为字符串并添加它们。

字符串格式化提供了一种更强大的方法来在字符串中嵌入非字符串。字符串格式化使用字符串的 format 方法来替换字符串中的多个参数。

例如:

# string formatting
nums = [4, 5, 6]
msg = "Numbers: {0} {1} {2}". format(nums[0], nums[1], nums[2])
print(msg)
结果:
Numbers: 4 5 6

format 函数的每个参数都放在相应位置的字符串中,这个位置是用花括号{}确定的。

字符串格式化也可以使用命名参数完成。、

a = "{x}, {y}".format(x=5, y=12)
print(a)
结果:
5,12

字符串格式化总结

总结:

1、按照默认顺序,不指定位置

print("{} {}".format("hello","world") )

hello world

2、设置指定位置,可以多次使用

print("{0} {1} {0}".format("hello","or"))

hello or hello

3、使用列表格式化

person = {"name":"W3Cschool","age":5}

print("My name is {name} . I am {age} years old .".format(**person))

My name is W3Cschool . I am 5 years old .

4、通过列表格式化

stu = ["W3Cschool","linux","MySQL","Python"]

print("My name is {0[0]} , I love {0[1]} !".format(stu))

My name is W3Cschool , I love linux !

字符串函数

Python 包含许多有用的内置函数和方法来完成常见的任务。

join - 以另一个字符串作为分隔符连接字符串列表。

replace - 用另一个替换字符串中的一个子字符串。

startswith 和 endswith - 确定是否在字符串的开始和结尾处有一个子字符串。

要更改字符串的大小写,可以使用 lowerupper

split 方法与 join 相反,把一个字符串转换成一个列表。

print(", ".join(["spam", "eggs", "ham"]))
#打印 "spam, eggs, ham"
print("Hello ME".replace("ME", "world"))
#打印 "Hello world"
print("This is a sentence.".startswith("This"))
# 打印 "True"
print("This is a sentence.".endswith("sentence."))
# 打印 "True"
print("This is a sentence.".upper())
# 打印 "THIS IS A SENTENCE."
print("AN ALL CAPS SENTENCE".lower())
#打印  "an all caps sentence"
print("spam, eggs, ham".split(", "))
#打印  "['spam', 'eggs', 'ham']"

结果:

spam, eggs, ham
Hello world
True
True
THIS IS A SENTENCE.
an all caps sentence
['spam', 'eggs', 'ham']

数字函数

要查找某些数字或列表的最大值或最小值,可以使用 maxmin

要将数字转成绝对值(该数字与0的距离),请使用 abs

要将数字四舍五入到一定的小数位数,请使用 round

要计算一个列表数字的总和,请使用 sum

print(min(1, 6, 3, 4, 0, 7, 1))
print(max([1, 2, 9, 2, 4, 7, 8]))
print(abs(-93))
print(abs(22))
print(sum([1, 2, 3, 4, 5, 6]))
结果:
0
9
93
22
21

列表函数

allany 将列表作为参数, 通常在条件语句中使用。

all 列表中所有值均为 True 时,结果为 True,否则结果为 False。

any 列表中只要有一个为 True,结果为 True,反之结果为 False。

enumerate 函数可以用来同时迭代列表的键和值

nums = [55, 44, 33, 22, 11]

if all([i > 5 for i in nums]):
   print("All larger than 5")

if any([i % 2 == 0 for i in nums]):
   print("At least one is even")

for v in enumerate(nums):
   print(v)
  结果:
All larger than 5
At least one is even
(0, 55)
(1, 44)
(2, 33)
(3, 22)
(4, 11)

文本分析

这是一个示例项目,展示了一个分析示例文件以查找每个字符占用的文本百分比的程序。

filename = input("输入一个文件名: ")

with open(filename) as f:
   text = f.read()

print(text)

程序的下一部分将查找每个字母占据文本的百分比。

def count_char(text, char):
  count = 0
  for c in text:    #2,循环打开的文件内容
    if c == char:    #3,内容有等于char 则输出0+1次,出现多次就再加1
      count += 1
  return count       #4,最终返回出现的总数

filename = input("输入一个文件名: ")
with open(filename) as f:
  text = f.read()
  
print(count_char(text, "r"))  #1,输出文件名,text ==文件名


for char in "abcdefghijklmnopqrstuvwxyz":
  perc = 100 * count_char(text, char) / len(text)
  print("{0} - {1}%".format(char, round(perc, 2)))

二,python3进阶知识重点

1,函数式编程

函数式编程是一种编程风格(顾名思义)是基于函数的。

函数式编程的关键部分是高阶函数。在上一课中,我们已经将这个想法简单地看作是对象的功能。高阶函数将其他函数作为参数,或将其作为结果返回。

例如:

def apply_twice(func, arg):   #func= add_five了,
   return func(func(arg))    # 返回 +5(+5(10))== 5+(5+(10))

def add_five(x):
   return x + 5    #如果改成x * 5 的话, 结果就会变成*5(*5(10))= 250了

print(apply_twice(add_five, 10))
结果:
20

函数 apply_twice 将另一个函数作为参数,并在其内部调用两次。

1,纯函数

函数式编程试图使用纯函数。纯函数没有副作用,并且返回一个仅依赖于它们的参数的值。

这是数学工作中的函数:例如,对于相同的 x,cos(x) 总是返回相同的结果。

纯函数的例子:

def pure_function(x, y):
  temp = x + 2*y
  return temp / (2*x + y)

非纯函数的例子:

some_list = []

def impure(arg):
  some_list.append(arg)
  
上面的函数不是纯函数,因为它改变了 some_list 的状态。

纯函数优点和缺点。

纯函数具备:

- 更容易推理和测试。

- 更高效。

一旦函数有一个输入,结果可以被存储并在下一次需要该输入的函数时被引用,从而减少函数被调用的次数。

- 更容易并行运行。

仅使用纯函数的主要缺点是它们主要使 I/O 的其他简单任务复杂化。

在某些情况下,他们也可能更难编写。

2, Lambda 表达式

正常创建一个函数(使用 def)会自动将其分配给一个变量。

这与其他对象(如字符串和整数)的创建不同,它们可以在运行中创建,而不必将其分配给变量。

使用 lambda 语法创建函数。这种方式创建的函数被称为匿名函数

将一个简单函数作为参数传递给另一个函数时,这种方法是最常用的。

语法如下:

lambda 参数列表: 表达式
def my_func(f, arg):
  return f(arg)

my_func(lambda x: 2*x*x, 5) # x表示参数

Lambda 函数从 lambon 演算中得名,这是 Alonzo Church 发明的计算模型。

Lambda 函数不如命名函数强大。

他们只能做需要单一表达的事情 - 通常相当于一行代码。

例如:

#命名函数
def polynomial(x):
    return x**2 + 5*x + 4
print(polynomial(-4))

#lambda
print((lambda x: x**2 + 5*x + 4) (-4))  #-4的平方16 +(-20)+4=0 

可以将 Lambda 函数分配给变量,并像普通函数一样使用。

例如:

double = lambda x: x * 2
print(double(7))
结果:
14

但是,很少这样做 - 用 def 定义一个函数通常会更好。

3, map和filter 函数

内置的函数 mapfilter 是在列表(或类似的称为迭代的对象)上运行的非常有用的高阶函数。

函数 map 接受一个函数和一个迭代器作为参数,并返回一个新的迭代器,该函数应用于每个参数。

例如:

def add_five(x):
  return x + 5

nums = [11, 22, 33, 44, 55]
result = list(map(add_five, nums))
print(result)
结果:
[16, 27, 38, 49, 60]

通过使用 lambda 语法,我们可以更容易地获得相同的结果。

nums = [11, 22, 33, 44, 55]

result = list(map(lambda x: x+5, nums))
print(result)
为了将结果转换成列表,我们使用了 list 函数。

filter 函数通过删除与谓词(一个返回布尔值的函数)不匹配的项来过滤一个迭代。

语法:

filter(function, iterable)
  • function -- 判断函数。
  • iterable -- 可迭代对象

下面我们通过一个实例来说明:

nums = [11, 22, 33, 44, 55]
res = list(filter(lambda x: x%2==0, nums))  #可以匹配的结果就打印出来
print(res)
结果:
[22,44]

与 map 一样,如果要打印结果,必须将结果显式转换为列表。

4,生成器

生成器是一种可迭代的类型,如列表或元组。

与列表不同的是,它们不允许使用任意索引,但是它们仍然可以通过 for 循环迭代。

可以使用 函数yield 语句来创建它们。

例如:

def countdown():
  i=5
  while i > 0:
    yield i
    i -= 1
    
for i in countdown():
  print(i)
  结果:
5
4    
3
2
1

yield 语句用于定义一个生成器,替换函数的返回值以向调用者提供结果而不破坏局部变量。

5, 集合

集合是数据结构,类似于列表或字典。集合使用花括号set 函数创建。

它们与列表共享一些功能,例如使用 in 来检查它们是否包含特定项目。

num_set = {1, 2, 3, 4, 5}
word_set = set(["spam", "eggs", "sausage"])

print(3 in num_set)
print("spam" not in word_set)

结果:

True
False

集合在几个方面不同于列表,但共享几个列表操作,如 len

集合是无序的,这意味着他们不能被索引。

集合不能包含重复的元素。

由于存储的方式,检查一个项目是否是一个集合的一部分比检查是不是列表的一部分更快

集合使用 add 添加元素,而不是使用 append

remove 方法从集合中删除特定的元素; pop 删除随机的元素。

nums = {1, 2, 1, 3, 1, 4, 5, 6}
print(nums)
nums.add(-7)
nums.remove(3)
print(nums)
结果:
{1, 2, 3, 4, 5, 6}
{1, 2, 4, 5, 6, -7}

通常使用集合来消除重复的条目。

集合可以使用数学运算进行组合。

联合运算符 | 结合两个集合形成一个包含两个集合任一项目的新集合。

相交运算符& 获得两个集合共有的项目

差运算符 - 获取第一集合中的项目,但不是第二集合中的项目。

对称差分运算符^ 获取任集合中非共有的项目。

first = {1, 2, 3, 4, 5, 6}
second = {4, 5, 6, 7, 8, 9}

print(first | second)
print(first & second)
print(first - second)
print(second - first)
print(first ^ second)
结果:
{1, 2, 3, 4, 5, 6, 7, 8, 9}
{4, 5, 6}
{1, 2, 3}
{8, 9, 7}
{1, 2, 3, 7, 8, 9}

数据结构

正如我们在前面的课程中所看到的,Python支持以下数据结构:列表,字典,元组,集合。

何时使用字典:

- 当您需要键:值对之间的逻辑关联时。

- 当您需要基于自定义密钥快速查找数据时。

- 当你的数据不断修改时。请记住,字典是可变的。

何时使用其他类型:

- 如果您有一些不需要随机访问的数据集合,请使用列表。当你需要一个简单的,可迭代的频繁修改的集合可以使用列表。

- 如果你需要元素的唯一性,使用集合。

- 当数据无法更改时使用元组。

很多时候,元组与字典结合使用,例如元组可能代表一个关键字,因为它是不可变的。

6 内建模块 itertools

itertools 模块是一个标准库,包含了几个在函数式编程中很有用的函数。

一种类型的函数是无限迭代器。

count 函数从一个值无限增加。

cycle 函数无限次迭代(例如列表或字符串)。

repeat 函数重复一个对象,无论是无限还是特定的次数。

例如:

from itertools import count

for i in count(3):
  print(i)
  if i >=11:
    break
  结果:
3         #从3开始无限增加,一直到11为止
4
5
6
7
8
9
10
11

itertools 中有许多功能可以在迭代器上运行,类似于映射和过滤。

例如:

takewhile - 当判定函数(返回值为 True 或 False)保持为True时,从迭代中取得项目;

chain - 将几个迭代结合成一个长整数;

accumulate - 以可迭代的方式返回一个正在运行的值。

from itertools import accumulate, takewhile

nums = list(accumulate(range(8)))
print(nums)
print(list(takewhile(lambda x: x<= 6, nums)))
结果:
[0, 1, 3, 6, 10, 15, 21, 28]  #0+0=0,0+1=1,1+2=3,3+3=6,6+4=10,10+5=15,15+6=21,21+7=28,0-7范围
[0, 1, 3, 6]

itertool中还有几个组合函数,比如 productpermutation。

当你想用一些项目的所有可能的组合来完成任务时使用。

例如:

from itertools import product, permutations

letters = ("A", "B")
print(list(product(letters, range(2))))  # 输出0-1和AB的各种组合
print(list(permutations(letters)))   #输出AB的各种可能的组合

结果:

[('A', 0), ('A', 1), ('B', 0), ('B', 1)]  
[('A', 'B'), ('B', 'A')]

小节练习

def power(x, y):
    if y == 0:
        return 1
    else:
        return x * power(x, y-1)

print(power(3, 3))    # 3* power(3,2)  3*3*3 

结果:
27

print(power(3, 4)) #输出 3* power(3,3) 3*3*3*3 
结果:81

2,面向对象编程

1,类

我们先前看过两种编程模式 - 命令式(使用语句,循环和函数)和 函数式(使用纯函数,高阶函数和递归)。

另一个非常流行的范例是面向对象编程(OOP)

对象是使用类来创建的,而这些类实际上是 OOP 的模具。

这个类描述了这个对象是什么,但是和对象本身是分开的。换句话说,一个类可以被描述为一个对象的蓝图,描述或定义。

您可以使用相同的类作为创建多个不同对象的蓝图。

类是使用关键字 class 和一个包含类方法的缩进块创建的。

下面是一个简单的类和它的对象的例子。

class Cat:
    def __init__(self, color, legs):
        self.color = color
        self.legs = legs
felix = Cat("ginger", 4)
rover = Cat("dog-colored", 4)
stumpy = Cat("brown", 3)

print("felix:",felix.__dict__) #dict是用来存储对象属性的一个字典,其键为属性名,值为属性的值.
print("rover:",rover.__dict__)
print("stumpy:",stumpy.__dict__)

结果:
felix: {'color': 'ginger', 'legs': 4}
rover: {'color': 'dog-colored', 'legs': 4}
stumpy: {'color': 'brown', 'legs': 3}

这段代码定义了一个名为 Cat 的类,它有两个属性:color 和 legs。
然后这个类被用来创建这个类的3个独立的对象.

__init__

__init__ 方法是一个类中最重要的方法。

这是在创建类的实例(对象)时使用类名称作为函数调用的。

所有的方法都必须以 self 作为自己的第一个参数,虽然它没有被明确地传递,但是 Python 为自己添加了自变量;

在调用方法时,不需要包含它。在一个方法定义中,self 指的是调用该方法的实例。

注意: __init__ 是两个下划线, 不是一个下划线 _init_

类的实例具有属性,这些属性是与它们相关联的数据片段。

在这个例子中,Cat 实例具有属性 color 和 legs。这些可以通过在一个实例之后加一个点和属性名来访问。

__init__ 方法中,可以使用 self.attribute 来设置实例属性的初始值。

例如:

class Cat:
  def __init__(self, color, legs):
    self.color = color
    self.legs = legs

felix = Cat("ginger", 4)
print(felix.color)
print(felix.legs)

结果:
ginger
4
在上面的例子中,__init__ 方法接受两个参数并将它们分配给对象的属性。__init__ 方法被称为类构造函数。

2,继承

继承提供了一种在类之间共享功能的方法。

想象几个类,Cat,Dog,Rabbit等。虽然它们在某些方面可能有所不同(只有 Dog 可能有 bark 方法),但它们可能在其他方面相似(都具有 color 和 name 的属性)。

这种相似性可以通过使它们全部从包含共享功能的超类 Animal 中继承来表示。

要从另一个类继承一个类,请将超类名放在类名后面的括号中。

例如:

class Animal: 
  def __init__(self, name, color):
    self.name = name
    self.color = color

class Cat(Animal):
  def purr(self):
    print("Purr...")
        
class Dog(Animal):
  def bark(self):
    print("Woof!")

fido = Dog("Fido", "brown")
print(fido.color)
fido.bark()
结果:
brown
woof!

从另一个类继承的类称为子类

被继承的类被称为超类。

如果一个类继承了另一个具有相同属性或方法的类,它的属性和方法将覆盖它们。

class Wolf: 
  def __init__(self, name, color):
    self.name = name
    self.color = color

  def bark(self):
    print("Grr...")

class Dog(Wolf):
  def bark(self):
    print("Woof")
        
husky = Dog("Max", "grey")
husky.bark()

结果:
woof
在上面的例子中,Wolf 是超类,Dog 是子类。

继承也可以是间接的。一个类B继承类A,而类C也可以继承类B。

class A:
  def method(self):
    print("A method")
    
class B(A):
  def another_method(self):
    print("B method")
    
class C(B):
  def third_method(self):
    print("C method")
    
c = C()
c.method()
c.another_method()
c.third_method()

结果:
A method
B method
C method
但是,不允许循环继承。

super 函数是一个与父类继承相关的函数。它可以用来在对象的超类中找到具有特定名称的方法。

例如:

class A:
  def spam(self):
    print(1)

class B(A):
  def spam(self):
    print(2)
    super().spam()
            
B().spam()
结果:
2
1
super().spam() 是调用超类的 spam 方法。

3,魔术方法和操作符重载

魔术方法是在名称的开始和结尾都有双下划线的特殊方法。

到目前为止,我们唯一遇到的是 __init__,但还有其他几个。

它们被用来创建不能用普通方法表示的功能。

它们的一个常见用途是运算符重载

这意味着为自定义类定义运算符,允许使用 + 和 * 等运算符。

例子中魔术方法是 __add__ 重载 +。

class Vector2D:
  def __init__(self, x, y):
    self.x = x
    self.y = y
  def __add__(self, other):
    return Vector2D(self.x + other.x, self.y + other.y)

first = Vector2D(5, 7)
second = Vector2D(3, 9)
result = first + second
print(result.x)
print(result.y)
结果:
8
16

__add__ 方法允许为我们的类中的 + 运算符定义自定义行为。
正如你所看到的,它添加了对象的相应属性并返回一个包含结果的新对象。
一旦定义了,我们就可以将这个类的两个对象相加。

魔术方法

常见的魔术方法: 

__sub__ 对应 -
__mul__ 对应 *
__truediv__ 对应 /
__floordiv__ 对应 //
__mod__ 对应 %
__pow__ 对应 **
__and__ 对应 &
__xor__ 对应 ^
__or__ 对应 |

表达式 x + y 被翻译成 x.__add__(y)。
然而,如果 x 没有实现 __add__,并且 x 和 y 的类型不同,则调用 y.__radd__(x)。
对于刚刚提到的所有魔法方法,都有等价的方法。

class SpecialString:
  def __init__(self, cont):
    self.cont = cont

  def __truediv__(self, other):
    line = "=" * len(other.cont)
    return "\n".join([self.cont, line, other.cont])

spam = SpecialString("spam")
hello = SpecialString("Hello world!")
print(spam / hello)

结果:
spam
============
Hello world!

在上面的例子中,我们为我们的类 SpecialString 定义了除法操作。
Python 也为比较运算提供了魔术方法。

__lt__ 对应 <
__le__ 对应 <=
__eq__ 对应 ==
__ne__ 对应 !=
__gt__ 对应 >
__ge__ 对应 >=

如果 __ne__ 没有被实现,它将返回 __eq__ 相反的结果。

其他比较运算符之间没有其他关系。

例如:
class SpecialString:
  def __init__(self, cont):
    self.cont = cont

  def __gt__(self, other):
    for index in range(len(other.cont)+1):
      result = other.cont[:index] + ">" + self.cont
      result += ">" + other.cont[index:]
      print(result)

spam = SpecialString("spam")
eggs = SpecialString("eggs")
spam > eggs

结果:
>spam>eggs
e>spam>ggs
eg>spam>gs
egg>spam>s
eggs>spam>
如您所见,您可以为重载操作符定义任何自定义行为
有几个神奇的方法使类像容器一样行事。

__len__ 对应 len()
__getitem__ 对应 获取索引
__setitem__ 对应 分配索引值
__delitem__ 对应 删除索引值
__iter__ 对应 迭代对象(例如for循环)
__contains__ 对应 in

还有很多其他的魔术方法,我们不会在这里介绍,比如将 __call__ 作为函数调用对象,__int__,__str__ 等等,将对象转换为内建类型。

3,正则表达式

1,介绍

Python 中的正则表达式可以使用 re 模块来访问,它是标准库的一部分。

定义正则表达式之后,可以使用 re.match 函数来确定字符串的开头是否匹配。

如果匹配,match 返回表示匹配的对象,否则返回 None。

为了避免在处理正则表达式时出现混淆,我们使用原始字符串 r"expression"

原始字符串不会转义任何东西,这使得使用正则表达式更容易。

import re

pattern = r"spam"

if re.match(pattern, "spamspamspam"):
   print("Match")
else:
   print("No match")
  结果:
  match
 上面的例子检查字符串是否匹配 "spam",如果是,则打印 "Match"。

其他的正则函数是 re.search 和 re.findall。

re.search 函数在字符串中的任何位置找到匹配的模式。

re.findall 函数返回一个与模式匹配的所有子串的列表。

例如:

import re

pattern = r"spam"

if re.match(pattern, "eggspamsausagespam"):
   print("Match")
else:
   print("No match")

if re.search(pattern, "eggspamsausagespam"):
   print("Match")
else:
   print("No match")
    
print(re.findall(pattern, "eggspamsausagespam"))
结果:
No match
Match
['spam', 'spam']

在上面的示例中,匹配函数与模式不匹配,因为它从字符串的开头开始匹配。
search 函数找到了匹配的字符串。

函数 re.finditer 和 re.findall 类似,不过它返回一个迭代器,而不是一个列表。

正则表达式搜索使用多个方法返回一个对象,提供有关它的详细信息。

这些方法包括返回匹配的字符串的组,返回第一个匹配的开始和结束位置的开始和结束,以及将第一个匹配的开始和结束位置作为元组返回的跨度。

例如:

import re

pattern = r"pam"

match = re.search(pattern, "eggspamsausage")
if match:
   print(match.group())
   print(match.start())
   print(match.end())
   print(match.span())
   结果:
pam
4
7
(4, 7)

使用正则表达式的最重要的 re 方法是 sub。

语法:

re.sub(pattern, repl, string, max=0)

此方法用 repl 替换字符串中所有出现的模式,除非提供 max限定修改数量。

sub 方法返回修改后的字符串。

例如:

import re

str = "My name is Loen. Hi Loen."
pattern = r"Loen"
newstr = re.sub(pattern, "Amy", str)  #str表示上面的变量
print(newstr)
结果:
My name is Amy. Hi Amy.

2,元字符

我们将看到的第一个元字符是 . (点)。

它匹配任何字符,但不匹配新的行。

import re

pattern = r"gr.y"

if re.match(pattern, "grey"):
   print("Match 1")

if re.match(pattern, "gray"):
   print("Match 2")

if re.match(pattern, "blue"):
   print("Match 3")
 结果:
Match 1
Match 2

接下来的两个元字符是 ^$

这两个分别匹配字符串的开始和结束。

例如:

import re

pattern = r"^gr.y$"

if re.match(pattern, "grey"):
   print("Match 1")

if re.match(pattern, "gray"):
   print("Match 2")

if re.match(pattern, "stingray"):
   print("Match 3")
  结果:
Match 1
Match 2

模式 “^gr.y$” 表示字符串应该以gr开头,然后跟随一个任何字符,除了换行符,并以y结尾。

3,字符类

字符类提供了一种只匹配特定字符集中的一个的方法。

通过将匹配的字符放在方括号内来创建字符类。

import re

pattern = r"[aeiou]"

if re.search(pattern, "grey"):
   print("Match 1")

if re.search(pattern, "qwertyuiop"):
   print("Match 2")

if re.search(pattern, "rhythm myths"):
   print("Match 3")
结果:
match 1
match 2
   

搜索函数中的模式 [aeiou] 匹配包含任何一个定义的字符的所有字符串。

字符类也可以匹配字符的范围。

一些例子:

[a-z] 匹配任何小写字母字符。

[G-P] 匹配从 G 到 P 的任何大写字符。

[0-9] 匹配任何数字。

一个字符类可以包含多个范围。例如,[A-Za-z] 匹配任何一个字母。

例如:

import re

pattern = r"[A-Z][A-Z][0-9]"

if re.search(pattern, "LS8"):
   print("Match 1")

if re.search(pattern, "E3"):
   print("Match 2")

if re.search(pattern, "1ab"):
   print("Match 3")
   
 结果:
 Match 1
上例中的模式匹配包含两个大写字母后跟一个数字的字符串。

在字符类的开头放置一个 ^ 来反转它, 这使得它匹配除包含的字符之外的任何字符。

其他元字符(如 $ 和 .)在字符类中没有意义。

元字符 ^ 没有意义,除非它是一个字符类中的第一个字符。

例如:

import re

pattern = r"[^A-Z]"

if re.search(pattern, "this is all quiet"):
   print("Match 1")

if re.search(pattern, "AbCdEfG123"):
   print("Match 2")

if re.search(pattern, "THISISALLSHOUTING"):
   print("Match 3")
 结果:
 match 1
 match 2
模式[^A-Z]匹配不包括大写字母的所有字符。

4,更多的元字符

更多的元字符 *+{}

这些指定了重复次数。

元字符 表示 “零次或者多次重复以前的事情”。它匹配尽可能多的重复。 号前可以是一个单独的字符,一个类,或一组括在括号中的字符。

import re

pattern = r"egg(spam)*"

if re.match(pattern, "egg"):
   print("Match 1")

if re.match(pattern, "eggspamspamegg"):
   print("Match 2")

if re.match(pattern, "spam"):
   print("Match 3")
   结果:
Match 1
Match 2
上面的例子匹配以 "egg" 开头的字符串,并跟随零个或多个 "spam"。

元字符 + 非常相似,不同之处在于 + 是 “一个或多个重复”,而 是“零个或多个重复”。

例如:

import re

pattern = r"g+"

if re.match(pattern, "g"):
   print("Match 1")

if re.match(pattern, "gggggggggggggg"):
   print("Match 2")

if re.match(pattern, "abc"):
   print("Match 3")
  结果:
Match 1
Match 2

总结:
* 匹配0个或更多的前面的表达式。
+ 匹配1个或更多的前面的表达式。

元字符 ? 匹配 “零重复或一次重复”。

例如:

import re

pattern = r"ice(-)?cream"

if re.match(pattern, "ice-cream"):
   print("Match 1")

if re.match(pattern, "icecream"):
   print("Match 2")

if re.match(pattern, "sausages"):
   print("Match 3")

if re.match(pattern, "ice--ice"):
   print("Match 4")
 结果:
 match 1
 match 2

大括号可以用来表示两个数字之间的重复次数。

正则表达式 {x,y} 表示 “在x和y之间重复某事”。

因此 {0, 1} 与 ? 相同。

大括号如果第一个数字缺失,则将其视为零。如果第二个数字丢失,则被认为是无限的。

例如:

import re

pattern = r"9{1,3}$"

if re.match(pattern, "9"):
   print("Match 1")

if re.match(pattern, "999"):
   print("Match 2")

if re.match(pattern, "9999"):
   print("Match 3")
 结果:
Match 1
Match 2

"9{1,3}$" 匹配具有1到3个9的字符串。

5,分组

可以通过用圆括号围绕正则表达式的一部分来创建组。

这意味着一个组可以作为元字符的参数,如 * 和?。

import re

pattern = r"egg(spam)*"

if re.match(pattern, "egg"):
   print("Match 1")

if re.match(pattern, "eggspamspamspamegg"):
   print("Match 2")

if re.match(pattern, "spam"):
   print("Match 3")
   
(spam)代表上面示例模式中的一个组。   
   结果:
   match 1
   match 2

可以使用组功能访问匹配组中的内容。

可以调用 group(0) 或者 group() 返回整个匹配。

调用 group(n) ,n 要大于 0,返回匹配的第 n 个组。

groups() 返回所有匹配的分组。

例如:

import re

pattern = r"a(bc)(de)(f(g)h)i"

match = re.match(pattern, "abcdefghijklmnop")
if match:
   print(match.group())
   print(match.group(0))
   print(match.group(1))
   print(match.group(2))
   print(match.groups())
  结果:
abcdefghi
abcdefghi
bc
de
('bc', 'de', 'fgh', 'g')
从上面的例子可以看出,组可以嵌套。

另一个重要的元字符是 |

意思是与,比如 red|blue 匹配 "red"或者"blue"。

例如:

import re

pattern = r"gr(a|e)y"

match = re.match(pattern, "gray")
if match:
   print ("Match 1")

match = re.match(pattern, "grey")
if match:
   print ("Match 2")    

match = re.match(pattern, "griy")
if match:
    print ("Match 3")
  结果:
  match 1
  match 2

更有用的特殊序列是 dsw

这些分别匹配数字,空格和单词字符。

在 ASCII 模式下,它们相当于 [0-9],[t n r f v] 和 [a-zA-Z0-9_]。

在 Unicode 模式下,它们也匹配某些其他字符,例如,w 匹配带有重音的字母。

大写字母 - D,S 和 W - 这些特殊序列的版本意味着与小写字母相反的版本,例如,D 匹配任何不是数字的东西。

import re

pattern = r"(\D+\d)"

match = re.match(pattern, "Hi 999!")

if match:
   print("Match 1")

match = re.match(pattern, "1, 23, 456!")
if match:
   print("Match 2")

match = re.match(pattern, " ! $?")
if match:
    print("Match 3")
   结果:
  Match 1

(D+d) 匹配一个或多个非数字后跟一个数字。

其他特殊序列是 AZb

序列 AZ 分别匹配字符串的开头和结尾。

序列 b 匹配 wW 字符之间的空字符串,或 w 字符和字符串的开始或结尾。非正式地,它代表了单词之间的界限。

序列 B 匹配其他地方的空字符串。

例如:

import re

pattern = r"\b(cat)\b"

match = re.search(pattern, "The cat sat!")
if match:
   print ("Match 1")

match = re.search(pattern, "We s>cat<tered?")
if match:
   print ("Match 2")

match = re.search(pattern, "We scattered.")
if match:
   print ("Match 3")
   
结果:
match 1 
match 2
"\b(cat)\b"  基本上与单词边界包围的单词 "cat"  匹配。

main

如果我们将前一个示例的代码保存为 w3cschool.py 文件,则可以使用 w3cschool 名称将其作为模块导入到另一个脚本中。

w3cschool.py

def function():
   print("This is a module function")

if __name__=="__main__":
   print("This is a script") 

some_script.py

import w3cschool

w3cschool.function()
结果:
This is a module function

6,打包

在 Python 中,术语打包指的是将模块写成标准格式,以便其他程序员可以轻松安装和使用它们。

这包括使用模块 setuptoolsdistutils

打包第一步是正确组织现有文件。将所有要放入库的文件放在同一个父目录中。

该目录还应该包含一个名为 __init__.py 的文件,该文件可以是空白的,但必须存在于目录中

示例目录结构:

W3Cschool/
   LICENSE.txt
   README.txt
   setup.py
   w3c/
      __init__.py
      w3cschool.py
      w3cschool2.py
您可以根据需要在目录中放置尽可能多的脚本文件

__init__.py 文件的作用是什么呢?

__init__.py 最明显的作用就是使包和普通目录区分;其次可以在该文件中申明模块级别的import语句从而使其变成包级别可见。

打包的下一步是编写 setup.py 文件。

这包含组装软件包所需的信息,以便将其上传到 PyPI 并使用 pip (名称,版本等)进行安装。

setup.py 文件的示例:

from distutils.core import setup

setup(
   name='W3Cschool', 
   version='0.1dev',
   packages=['w3cschool',],
   license='MIT', 
   long_description=open('README.txt').read(),
)

创建 setup.py 文件后,将其上传到 PyPI,或使用命令行创建二进制分发(可执行安装程序)。

要构建源代码发行版,请使用命令行导航到包含 setup.py 的目录,然后运行 python setup.py sdist 命令。

运行 python setup.py bdist,或者对于Windows,使用 python setup.py bdist_wininst 来构建二进制分发。

使用 python setup.py register,然后用 python setup.py sdist upload 来上传一个包。

最后,用 python setup.py install 安装一个软件包。

为用户打包

上一课包含了供其他 Python 程序员使用的打包模块。但是,许多不是程序员的计算机用户没有安装 Python。

因此,将脚本打包为相关平台(如 Windows 或 Mac 操作系统)的可执行文件很有用。

这对于 Linux 来说不是必需的,因为大多数 Linux 用户的确已经安装了Python,并且能够像原来一样运行脚本。

对于 Windows,许多工具可用于将脚本转换为可执行文件。例如,py2exe 可用于将 Python 脚本及其所需的库打包到单个可执行文件中。

PyInstallercx_Freeze 服务于相同的目的。

Mac 使用 py2app,PyInstaller 或 cx_Freeze。

Last modification:April 27th, 2020 at 06:29 pm
如果觉得我的文章对你有用,请随意赞赏