友情提示:本文针对的是非编程零基础的朋友,可以帮助我们快速了解Python语法,接着就可以快乐的投入到实战环节了。如果是零基础,还是老老实实看书最为稳妥。

前言

​偶然在知乎上看到了一些好玩的Python项目(学 Python 都用来干嘛的?),让我对Python产生了些许兴趣。距离北漂实习还有两个月时间,正好可以在这段空闲时间里学一学。如果能做出些小工具,说不定对工作还有帮助,何乐而不为呢?

​关于环境的安装和IDE就不多说了,网上有很多教程。这里贴出一篇博客,大家按里面的步骤安装就行:VSCode搭建Python开发环境。使用VSCode主要是因为免费,而且有大量插件可以下载,大家可以尽情的定制自己的IDE。如果曾经没有使用过VSCode,最好多了解下哪些必须的插件,优化自己的Coding体验。比如:Python插件推荐。

​环境搭建好后,就可以愉快地敲代码了。VSCode需要自己创建Python文件,以.py为后缀。Ctrl+F5运行程序,F5调试程序。

Python基础

注释

​单行注释:#

​多行注释:''' (三个英文单引号开头,三个英文单引号结尾)

# 这是单行注释

'''

这是多行注释

'''

变量

​Python的变量定义不需要显式指明数据类型,直接【变量名=值】即可。注意变量名分大小写,如Name和name不是同一个变量。

name = "小王"

print(name) # 输出 小王

数据类型

​Python提供6种基础的数据类型:数字类型(number)、字符串类型(string)、列表(list)、元组(tuple)、字典(dictionary)、集合(set)。其中数字类型还包括三种数值类型:整型(int)、浮点型(float)、复数类型(complex)。

​列表、元组那些我们留在容器那一节里面讲,先看看数字类型。

浮点型

​浮点型表示小数,我们创建一个浮点型变量,再通过type函数看一看它的类型:

pi = 3.1415926

print(type(pi)) # 输出

​int整数型就不说了,其为Integer的缩写。

复数类型

​复数类型,所谓复数就是我们中学学的,实数+虚数,比如:

x = 10+1.2j # 虚数以j或J结尾

print(type(x)) # 输出

​刚开始接触复数时,很纳闷为啥会有这种类型,到底有啥实际作用,遂百度了一番:

mzy0324:微电子方面的运算基本全部都是复数运算。

hilevel:至少复数用来计算向量的旋转要比矩阵方便多了。科学计算和物理应该会用得到吧。PS:我经常把Python当带编程功能的计算器用,用来调试纯粹的数学算法挺方便的。

morris88:Python 的一大应用领域,主要是科学计算,主要用于太空宇航、银行等。

​联想到Python平时在算法、科学研究等领域应用颇多,所以也就明白了,只是自己没使用的需求而已。

字符串

​字符串类型的变量定义用一对双引号或者单引号括起来。如:

x = "Hello Python"

y = 'Hello Python'

print(x,y) # 输出Hello Python Hello Python

​字符串内置函数:

函数

作用

find(str[,start,end])

在字符串中查找子串str,可选参数start和end可以限定范围

count(str[,start,end])

在字符串中统计子串str的个数,可选参数start和end可以限定范围

replace(old,new[,count])

在字符串中用new子串替换old子串,可选参数count代表替换个数,默认全部替换

split(sep[,maxsplit])

用指定分隔符sep分割字符,返回一个列表,可选参数maxsplit代表分割几次,默认全部

upper()、lower()

转换大小写

join(序列)

把序列中的元素用指定字符隔开并生成一个字符串。

startwith(prefix[,start,end])

判断字符串中是否以prefix开头,返回bool类型。还有一个endwith,判断结尾的。

strip([,str])

去掉字符串开头和结尾的空白字符(包括\n、\t这些),可选参数代表可以去掉指定字符

布尔类型

​顺便再说一下布尔类型,不过与Java不同的是,布尔类型的True和False,首字母必须大写:

x = True

print(type(x)) # 输出

类型转换

​说完几个基本的数据类型,不免要提到类型转换。Python内置一些类型转换的函数:

函数名

作用

int(x)

将x转换为整型(小数转整型会去掉小数部分)

float(x)

将x转换为浮点型

str(x)

将x转换为字符串

tuple(x)

将x转换为元组

list(x)

将x转换为列表

set(x)

将x转换为集合,并去重

输入与输出

​输入函数为input。input函数返回用户输入的信息为字符串类型。所以如果你输入的是数字类型,记得类型转换。

x = input("请输入数字")

print(type(x),x) # 输出 10

​输出前面已经演示了很多次了,函数为print,可以直接输出变量与值。一次输出多个变量可以用逗号隔开,就想上面的演示一样,既要输出类型,也要输出值。不换行输出,可以在print函数里加上end=""这个参数,因为print默认end="\n",\n就是换行的意思。如果想输出特殊字符,可能需要用到转义字符:\。

x = 10

y = 20

print(x,y,end="") # 输出10 20 加上end="" 不换行

print("Hello \\n Python") # 输出 Hello \n Python

​在输出时,还可以格式化输出内容:%s代表字符串格式、%d代表整型、%f代表浮点型

z = 1.2

print("%f"%z) # 输出 1.200000

​除了格式化,%d等还可以当作占位符:

name = "小明"

age = 18

print("姓名:%s,年龄:%d"%(name,age)) # 姓名:小明,年龄:18

​如果你闲这个占位符麻烦,还可以使用format函数,占位符只用写一对{}:

print("姓名:{},年龄:{}".format(name,age)) # 姓名:小明,年龄:18

运算符

算术运算符

​除了加减乘除,还有幂(**)、取模(%)、取整(//)

x = 3 ** 2 # x=9 即3的2次方

y = 5 % 3 # y=2 即5除以3余2

z = 5 // 2 # z=2 即5除以2,整数部分为2

比较运算符

​和其他常用编程语言基本一模一样,不等于(!=)、大于等于(>=)、等于(==)。

赋值运算符

​Python也支持+=、*=等形式的赋值运算。除此之外,当然也支持前面说到的幂、取模等算术运算符,如取整并赋值(//=)、取模并赋值(%=)。

x = 10

x %= 3

print(x) # 输出1 ,x%=3 意为 x = x%3

逻辑运算符

​非(not)、与(and)、或(or)

x = True

print(not x) # 输出 False

if、while、for

​这三个和其他编程语言基本没差,就是写法上有点区别。首先没了大括号,条件语句后以冒号开头;代码快有严格的缩进要求,因为没了大括号,缩进就是条件语句判断自己代码快范围的依据。其他的基本一样,比如continue跳过当次循环,break跳出整个循环体。下面看三个简单的例子就明白了:

a = 10

# if或else后面是冒号,代码块还需要缩进

if a >= 10:

print("你好啊老大")

else:

print("滚蛋")

# 同样的while后面也需要冒号,代码块必须缩进。(Python没有num++,得写成num+=1)

# print想不换行打印,最后得加个end="",因为默认有一个end="\n"

# " "*(j-i),代表j-i个空格

i = 1

j = 4

while i <= j:

print(" "*(j-i), end="")

n = 1

while n <= 2*i-1:

print("*", end="")

n += 1

print("")

i += 1

# 语法:for 变量 in 序列 ,还没讲序列,暂时用range表示,代表1-21的序列

# continue略过当次循环,break跳出整个循环

for i in range(1, 21):

if i % 2 == 0:

if(i % 10 == 0):

continue

if(i >= 15):

break

print(i)

容器

列表

​列表使用一对[]定义,每个元素用逗号隔开,元素类型不强求相同,通过索引获取列表元素。具体的我们看下面的代码:

info_list = ["小红", 18, "男"] #可以不是同一类型

info_list[2] = "女" # 修改指定索引位置的元素

del info_list[1] # 删除指定索引位置的元素

info_list.remove("女") # 删除列表中指定的值

for att in info_list: # 遍历元素

print(att)

​上面的示例代码演示了部分列表的用法,下面再列出一些其他的常用函数或语法:

函数或语法

作用

list.append(element)

向列表list结尾添加元素(这个元素也可以是个列表)

list.insert(index,element)

向列表指定位置添加元素

list.extend(new_list)

向列表list添加new_list的所有元素

list.pop([,index])

弹出最后一个元素,可选参数index,弹出指定位置元素

list.sort([,reverse=True])

对列表排序,可选参数reverse=True表示降序

list[start:end]

对列表分片,start和end代表起始结束索引

list1+list2

拼接两个列表

元组

​元组用一对()定义。元组也是有序的,它和列表的区别就是,列表可以修改元素,元组不行。正是因为这个特点,元组占用的内存也比列表小。

name_list=("小红","小王")

字典

​字典使用一对{}定义,元素是键值对。用法示例如下:

user_info_dict = {"name": "小王", "age": "18", "gender": "男"}

name = user_info_dict["name"] # 直接用key获取value

age = user_info_dict.get("age") # 也可以用get(key)获取value

user_info_dict["tel"] = "13866663333" # 当key不存在,就是往字典添加键值对,如果存在就是修改value

del user_info_dict["tel"] # 删除指定键值对

​以上就是常用语法和函数。字典也可以遍历,只是遍历时,需要指定遍历的是key还是value,比如:

for k in dict.keys(): # 遍历所有key

for v in dict.values(): # 遍历所有value

for item in dict.items(): # 也可以直接遍历键值对

集合

​集合是无序的,也用一对{}定义,但不是键值对了,是单独且不重复的元素。部分用法如下:

user_id_set = {"1111","22222","3333"} # 元素不重复

print(type(user_id_set)) # 输出

# 除了直接用{}定义,还可以用set函数传入一个序列,其会为list去重,并返回一个集合(如果是字符串,字符串会被拆成字符)

new_user_id_set = set(list)

​上面演示了部分用法,下面我们用一个表格展示一些常用的函数或语法:

函数或语法

作用

element in set

判断元素是否在集合中,返回布尔类型

element not in set

判断元素是否不在集合中

set.add(element)

向集合添加元素

set.update(list,.....)

将序列中的每个元素去重并添加到集合中,如果有多个序列,用逗号隔开

set.remove(element)

删除指定元素,如果元素不存在就会报错

set.discard(element)

删除指定元素,如果元素不存在也不会报错

set.pop()

随机删除集合中的元素,并返回被删除的元素

set1 & set2 或set1 intersection set2

求两个集合的交集,两种用法结果一样

set1 | set2 或set1 union set2

求两个集合的并集

set1 - set2 或set1.difference(set2)

求两个集合的差集,注意顺序。set1-set2代表set1有set2没有的元素

函数

函数的定义

​Python中函数用def定义,格式为:

def function_name(参数列表): # 参数可为空,多个参数用逗号隔开

函数体

return 返回值 #可选

# 函数的调用

function_name(参数列表)

缺省参数

​和循环体一样的,因为没有了大括号,所以缩进是严格要求的。除了上面那种比较常见的格式,Python函数的参数中,还有一种缺省参数,即带有默认值的参数。调用带有缺省参数的函数时,可以不用传入缺省参数的值,如果传入了缺省参数的值,则会使用传入的值。

def num_add(x,y=10): # y为缺省函数,如果调用这个函数只传入了x的值,那么y默认为10

命名参数

​一般情况下,调用函数传入实参时,都会遵循参数列表的顺序。而命名参数的意思就是,调用函数时,通过参数名传入实参,这样可以不用按照参数定义的顺序传入实参。

def num_add(x, y):

print("x:{},y:{}".format(x, y))

return x+y

# 输出:

# x:10,y:5

# 15

print(num_add(y=5, x=10))

不定长参数

​不定长参数可以接收任意多个参数,Python中有两种方法接收:1.在参数前加一个*,传入的参数会放到元组里;2.在参数前加两个**,代表接收的是键值对形式的参数。

# 一个*

def eachNum(*args):

print(type(args))

for num in args:

print(num)

# 输出:

# ‘

# (1, 2, 3, 4, 5)

eachNum(1,2,3,4,5)

## 两个**。这个other是想告诉你,在使用不定长参数时,也可以搭配普通的参数

def user_info(other,**info):

print(type(info))

print("其他信息:{}".format(other))

for key in info.keys():

print("{} : {}".format(key,info[key]))

# 传入参数时,不用像定义字典一样,加个大括号再添加键值对,直接当命名参数传入即可

# 输出:

#

# 其他信息:管理员

# 略...

user_info("管理员",name="赵四",age=18,gender="男")

​上面示例代码中的注释说到了,当使用不定长参数时,不用像字典或者元组的定义那样,直接传入参数即可。但有时候,可能会遇到想把字典、元组等容器中的元素传入到不定长参数的函数中,这个时候就需要用到拆包了。

​所谓拆包,其实就是在传入参数时,在容器前面加上一个或两个*。还是以上面的user_info函数为例:

user_info_dict={"name":"赵四","age":18,"gender":"男"}

user_info("管理员",**user_info_dict) # 效果和上面一样

​注意,如果接收方的不定长参数只用了一个 * 定义,那么传入实参时,也只能用一个 *。

匿名函数

​匿名函数,即没有名字的函数。在定义匿名函数时,既不需要名称,也不需要def关键字。语法如下:

lambda 参数列表: 表达式

​多个参数用逗号隔开,匿名函数会自动把表达式的结果return。在使用时,一般会用一个变量接收匿名函数,或者直接把匿名函数当参数传入。

sum = lambda x,y : x+y

print(sum(1,2)) # 输出3

闭包和装饰器

​在Python中,函数内还可以定义函数,外面这个函数我们就称为外部函数,里面的函数我们就称为内部函数。而外部函数的返回值是内部函数的引用,这种表达方式就是闭包。内部函数可以调用外部函数的变量,我们看一个示例:

# 外部函数

def sum_closure(x):

# 内部函数

def sum_inner(y):

return x+y

return sum_inner # 返回内部函数

# 获取了内部函数

var1 = sum_closure(1)

print(var1) # 输出.sum_inner at 0x000001D82900E0D0>,是个函数类型

print(var1(2)) # 输出3

​说完闭包的用法,接着了解一下装饰器。不知道大家了解过AOP没,即面向切面编程。说人话就是在目标函数前后加上一些公共函数,比如记录日志、权限判断等。Python中当然也提供了实现切面编程的方法,那就是装饰器。装饰器和闭包一起,可以很灵活的实现类似功能,下面看示例:

import datetime #如果没有这个包,在终端里输入pip3 install datetime

# 外部函数,其参数是目标函数

def log(func):

#内部函数,参数得和目标函数一致。也可以使用不定长参数,进一步提升程序灵活性

def do(x, y):

# 假装记录日志,执行切面函数。(第一次datetime是模块、第二个是类、now是方法。在下一节讲到模块)

print("时间:{}".format(datetime.datetime.now()))

print("记录日志")

# 执行目标函数

func(x, y)

return do

# @就是装饰器的语法糖,log外部函数

@ log

def something(x, y):

print(x+y)

# 调用目标函数

# 输出:

# 时间:2021-01-06 16:17:00.677198

# 记录日志

# 30

something(10, 20)

​函数相关的就说到这里了,其实还有一些知识没说到,比如变量的作用域、返回值等。这部分内容和其他语言几乎无异,一点区别无非就是返回值不用在乎类型了,毕竟定义函数时也没指定函数返回值类型,这一点各位老司机应该也会想到。

包和模块

​Python中包与普通文件夹的区别就是,包内要创建一个__init__.py文件,来标识它是一个包。这个文件可以是空白的,也可以定义一些初始化操作。当其他包下的模块调用本包下的模块时,会自动的执行__init__.py文件的内容。

模块

​一个Python文件就是一个模块,不同包下的模块可以重名,在使用的时候以“包名.模块名”区别。导入其他模块用import关键字,前面的示例代码中也演示过一次。导入多个模块可以用逗号隔开,也可以直接分开写。除了导入整个模块,还可以导入模块中指定的函数或类:

from model_name import func_name(or class_name)

​导入函数或类后,就不要使用模块名了,直接调用导入的类或函数即可。

面向对象

类和对象

​Python是一种面向对象的解释型编程语言。面向对象的关键就在于类和对象。Python中类的定义用class关键字,如下:

class 类名:

def 方法名(self[,参数列表])

...

​定义在类里面的函数叫做方法,只是与类外部的函数做个区分,不用在意叫法。类里面的方法,参数列表中会有一个默认的参数,表示当前对象,你可以当作Java中的this。因为一个类可以创建多个对象,有了self,Python就知道自己在操作哪个对象了。我们在调用这个方法时,不需要手动传入self。示例代码:

class Demo:

def do(self):

print(self)

# 创建两个Demmo类型的对象

demo1=Demo()

demo1.do() # 输出<__main__.demo object at>

demo2=Demo()

demo2.do() # 输出<__main__.demo object at>

print(type(demo1)) #

构造方法

​构造方法的作用是在创建一个类的对象时,对对象进行初始化操作。Python中类的构造方法的名称是__init__(两边分别两个下划线)。在创建对象时,__init__方法自动执行。和普通方法一样的,如果你想自定义构造方法,也要接收self参数。示例代码:

class Demo:

# 构造方法,还可以传入其他参数化

def __init__(self,var1,var2):

# 把参数设置到当前对象上,即使类中没有属性也可以设置

self.var1=var1

self.var2=var2

print("初始化完成")

def do(self):

print("Working...")

# 通过构造方法传入实参

demo1=Demo(66,77)

demo1.do()

# 通过当前对象,获取刚刚设置的参数

print(demo1.var1)

print(demo1.var2)

访问权限

​Java或C#中有好几种访问权限,在Python中,属性和方法前添加两个下划线即为私有,反之就是共公有。具有私有访问权限的属性和方法,只能在类的内部方法,外部无法访问。和其他语言一样,私有的目的是为了保证属性的准确性和安全性,示例代码如下:

class Demo:

# 为了方便理解,我们显示的设置一个私有属性

__num = 10

# 公有的操作方法,里面加上判断,保证数据的准确性

def do(self, temp):

if temp > 10:

self.__set(temp)

# 私有的设置方法,不让外部直接设置属性

def __set(self, temp):

self.__num = temp

# 公有的get方法

def get(self):

print(self.__num)

demo1 = Demo()

demo1.do(11)

demo1.get() # 输出 11

​一堆self.刚开始看时还有点晕乎,把它当作this就好。

继承

​继承是面向对象编程里另一大利器,好处之一就是代码重用。子类只能继承父类的公有属性和方法,Python的语法如下:

class SonClass(FatherClass):

​当我们创建一个SonClass对象时,直接可以用该对象调用FatherClass的公有方法。Python还支持多继承,如果是多继承就在小括号里把父类用逗号隔开。

​如果想在子类里面调用父类的方法,一般有两种方式:1.父类名.方法名(self[,参数列表])。此时的self是子类的self,且需要显示传入;2.super().方法名()。第二种方式因为没有指定父类,所以在多继承的情况下,如果调用了这些父类中同名的方法,Python实际会执行小括号里写在前面的父类中的方法。

​如果子类定义了与父类同名的方法,子类的方法就会覆盖父类的方法,这就是重写。

异常处理

捕获异常

​捕获异常的语法如下:

try:

代码快 # 可能发生异常的代码

except (异常类型,...) as err: # 多个异常类型用逗号隔开,如果只有一个异常类型可以不要小括号。err是取的别名

异常处理

finally:

代码快 # 无论如何都会执行

​在try代码块中,错误代码之后的代码是不会执行的,但不会影响到try ... except之外的代码。看个示例代码:

try:

open("123.txt") #打开不存在的文件,发生异常

print("hi") # 这行代码不会执行

except FileNotFoundError as err:

print("发生异常:{}".format(err)) # 异常处理

print("我是try except之外的代码") #正常执行

​虽然上面的内容和其他语言相差不大,但是刚刚接触Python鬼知道有哪些异常类型,有没有类似Java的Exception异常类型呢?肯定是有的。Python同样提供了Exception异常类型来捕获全部异常。

​那如果发生异常的代码没有用try except捕获呢?这种情况要么直接报错,程序停止运行。要么会被外部的try except捕获到,也就是说异常是可以传递的。比如func1发生异常没有捕获,func2调用了func1并用了try except,那么func1的异常会被传递到func2这里。是不是和Java的throws差不多?

抛出异常

​Python中抛出异常的关键字是raise,其作用和Java的throw new差不多。示例代码如下:

def do(x):

if(x>3): # 如果大于3就抛出异常

raise Exception("不能大于3") # 抛出异常,如果你知道具体的异常最好,后面的小括号可以写上异常信息

else:

print(x)

try:

do(4)

except Exception as err:

print("发生异常:{}".format(err)) # 输出 发生异常:不能大于3

文件操作

读写文件

​想要操作一个文件,首先得打开它。Python中有个内置的函数:open。使用open打开文件可以有三种模式,分别为:只读(默认的模式,只能读取文件内容,r表示)、只写(会覆盖原文本内容,w表示)、追加(新内容追加到末尾,a表示)。示例如下:

f = open("text.txt","a") # 用追加的方式获取文件对象

​因为text.txt和代码在同一目录所以只写了文件名,如果不在同一目录需要写好相对路径或绝对路径。

​获取到文件对象后,接下来就可以操作了,反正就是些API,直接看示例:

f = open("text.txt","a",encoding="utf-8") # 以追加的方式打开文件,并设置编码方式,因为接下来要写入中文

f.write("234567\n") # 写入数据,最后的\n是换行符,实现换行

f.writelines(["张三\n","赵四\n","王五\n"]) # write只能写一个字符串,writelines可以写入一列表的字符串

f.close() # 操作完记得关闭

​以上是写文件的两个方法。最后记得关闭文件,因为操作系统会把写入的内容缓存起来,万一系统崩溃,写入的数据就会丢失。虽然程序执行完文件会自动关闭,但是实际项目中,肯定不止这点代码。Python也很贴心,防止我们忘了close,提供了一种安全打开文件的方式,语法是 with open() as 别名:,示例如下

with open("test.txt","w") as f: # 安全打开文件,不需要close。

f.write("123")

​写完了,该读一读了。示例如下:

f = open("text.txt","r",encoding="utf-8")

data = f.read() # read会一次性读出所有内容

print(data)

f.close()

​除了一次性读取完,还可以按行的方式返回全部内容,并用一个列表装起来,这样我们就可以进行遍历了。方法是readlines,示例如下:

f = open("text.txt","r",encoding="utf-8")

lines = f.readlines() # lines是个列表

for line in lines:

print(line)

f.close()

文件管理

​在操作文件的时候,肯定不止读写这么简单,可能还会涉及文件的删除、重命名、创建等等。在用Python的函数操作文件之前,需要导入os模式:import os 。下面简单的演示一下重命名的函数,其他的函数我们以表格的形式展现。

import os

os.rename("text.txt","123.txt") # 把text.txt改名为123.txt

函数

作用

os.remove(path)

删除指定文件

os.mkdir(path)

在指定路径下创建新文件

os.getcwd()

获取程序运行的绝对路径

os.listdir(path)

获取指定路径下的文件列表,包含文件和文件夹

os.redir(path)

删除指定路径下的空文件夹(如果不是空文件夹就会报错)

操作JSON

​学了前面的容器,会发现JSON的格式和Python的字典有点像,都是键值对形式的。虽然格式很像,但还是有点小区别,比如:Python的元组和列表在JSON中都是列表、Python的True和Flase会被转换成小写、空类型None会被转换成null。下面我们来看一些具体的函数把。

​在Python中操作JSON格式的数据需要导入json模块。同样的,我这里只演示一个函数,其他常用的用表格列出来。

import json

user_info={"name":"张三","age":18,"gender":"男","hobby":("唱歌","跳舞","打篮球"),"other":None} # 创建一个字典

json_str=json.dumps(user_info,ensure_ascii=False) # dumps函数会把字典转换为json字符串

# 输出 {"name": "张三", "age": 18, "gender": "男", "hobby": ["唱歌", "跳舞", "打篮球"], "other": null}

print(json_str)

​需要注意如果数据存在中文,需要在dumps函数加上ensure_ascii=False。

函数

作用

json.loads(json_str)

把json字符串转换为Python数据结构

json.dump(user_info,file)

把Python数据写入到json文件,要先获取文件,那个file就是文件对象

json.load(file)

把json文件中的数据转为成Python数据结构,同样需要获取文件

​关于JSON的操作就说这些。通用的数据格式不止JSON一种,比如还有xml、csv等。为了节约篇幅,就不再赘述了,大家可以根据自己的需求查对应的API即可。

正则表达式

​最后一节讲正则表达式,一是因为这也算个基础知识,在很多地方都有可能用到。二是因为后面的爬虫实战,肯定会用到正则表达式来解析各种数据。

​Python中内置了re模块来处理正常表达式,有了这个模块我们就可以很方便的对字符串进行各种规则匹配检查。不过正则表达式真正难的是表达式的书写,函数主要就一个:re.match(pattern,string),其中pattren就是正则表达式,stirng就是待匹配字符串。如果匹配成功就会返回一个Match对象,否则就返回None。匹配是从左往右,如果不匹配就直接返回None,不会接着匹配下去。示例如下:

import re

res=re.match("asd","asdabcqwe") # 匹配字符串中是否有asd(如果asd不在开头就会返回None)

print(res) # 输出

print(res.group()) # 输出 asd 如果想获取匹配的子字符就用这个函数

​秉着帮人帮到底的精神,下面就简单的介绍下正则表达式的一些规则。

单字符匹配

​单字符匹配,顾名思义就是匹配一个字符。除了直接使用某个具体的字符,还可以使用以下符号来进行匹配:

符号

作用

.

匹配除”\n“以外的任意单个字符

\d

匹配0-9之间的一个数字,等价于[0-9]

\D

匹配一个非数字字符,等价于[^0-9]

\s

匹配任意空白字符,如空格、\t、\n等

\S

匹配任意非空白字符

\w

匹配单词字符,包括字母、数字、下划线

\W

匹配非单词字符

[]

匹配[]中列举的字符,比如[abc],只要出现这三个字母中的一个即可匹配

​以防有的朋友从未接触过正则表达式,不知道怎么用,下面我来做个简答的演示。假如我想匹配三个字符:第一个是数字、第二个是空格、第三个是字母,一起来看看怎么写这个正则表达式吧:

import re

pattern = "\d\s\w" # \d匹配数字、\s匹配空格、\w匹配字母(切记是从左往右依次匹配的,只要有一个字符匹配不上就直接返回None)

string = "2 z你好"

res=re.match(pattern,string)

print(res.group()) # 输出:2 z

​看到这你可能会想,非得一个个字符匹配,那多麻烦啊,有没有更灵活的规则?当然有了,接着看。

数量表示

​如果我们只想匹配字母,但不限制有多少个,该怎么写呢?看下面的表格就知道了:

符号

作用

*

匹配一个字符出现0次或多次

+

匹配一个字符至少出现一次,等价于{,1}

?

匹配一个字符出现0次或1次,等价于{1,2}

{m}

匹配一个字符出现m次

{m,}

匹配一个字符至少出现m次

{m,n}

匹配一个字符出现m到n次

​数量匹配的符号后面如果加上?,就会尽可能少的去匹配字符,在Python里面叫非贪婪模式,反之默认的就是贪婪模式。比如{m,}会尽可能多的去匹配字符,而{m,}?在满足至少有m个的情况下尽可能少的去匹配字符。其他的同理。

​来看一个例子,我想匹配开头是任意个小写字母,接着是1到5个2-6的数字,最后是至少一个空格:

import re

pat = r"[a-z]*[2-6]{1,5}\s+"

str = "abc423 你好"

res=re.match(pat,str)

print(res) #输出 abc423

​我们来解析下这个正则表达式,pat字符串开头的r是告诉Python这是个正则表达式,不要转义里面的\,建议写表达式时都加上。[a-z]代表任意小写字母,不用\w的原因是,\w还包括数字、下划线,没有严格符合我们的要求。加上个*就代表任意数量。这里强调一下单字符匹配和数量表示之间的逻辑关系,以[a-z]*为例,其表达的是任意个[a-z],而不是某个字母有任意个。明白了这个逻辑后,其他的也好理解了。

​前面的例子都是我随意编的,其实学了这些,已经可以写出一个有实际作用的表达式了,比如我们来匹配一个手机号。首先手机号只有11位,第一个数字必须是1,第二个是3、5、7、8中的一个。知道了这三个个规律,我们来写一下表达式:1[3578]\d{9}。看上去好像可以,但是仔细一想,前面不是说了正则表达式是从左往右匹配,只要符合了就会返回结果,也不会管字符串匹配完全没有。如果最后有10个数字,这个表达式也会匹配成功。关于这个问题我们接着看。

边界表示

​边界表示符有两个:开头^和结尾$。使用起来也很简单,还是以上面的手机号为例,我们再来完善一下:^1[3578]\d{9}$。其中^1表示以1开头,\d{9}$表示以9个数字结尾。其实这个^1可有可无,毕竟是从左往右的,字符串不是1开头的话直接就会返回None,但是这个结尾符是必须的。

转义字符

​假如我们想匹配的字符与正则表达式规定的这些字符一样该怎么办?比如我们想单纯的匹配.这个字符,但是这个字符在正则表达式中表示的是任意字符。这时候就要用到转义字符\了。其实这个转义字符在很多语言里都是一样的。那么前面的例子就可以写出\.。我们再演示个匹配邮箱的例子:

import re

pat = r"^\w{4,10}@qq\.com" # 如果.前面不加\,就代表任意字符了

str = "1234@qq.com"

res=re.match(pat,str)

print(res)

匹配分组

​看到上面的匹配邮箱例子,是不是有个疑问,如果我想不止匹配QQ邮箱该怎么办呢。那就要用到分组了,其可以实现匹配多种情况。分组符号如下:

符号

作用

()

将括号里的内容当作一个分组,每个分组会有一个编号,从1开始

|

连接多个表达式,表达式之间是“或”的关系,可与()一起使用

\num

引用分组,num代表分组编号

(?P...)

给分组取别名,别名写在表达式前面,name不用打引号

(?P=name)

根据别名使用分组中的正则表达式

​那么我们把上面的例子稍微修改下:^\w{4,10}@(qq|163|outlook|gmail)\.com。这样就可以匹配多种邮箱了。

​简单的演示了下|的用法,大家可能对其他的分组符号还有点疑惑,下面我们再来演示一下这些符号:

import re

pat = r".*"

str = "

res=re.match(pat,str)

print(res)

​这个表达式匹配的是由两个标签组成的html字符串。第一眼看上去有点麻烦,实际很简单。再次强调一下,普通字符也可以当表达式来匹配的,比如上面的< >就是普通字符而已。

​我们来分析一下这个表达式,首先一对小括号表示一个分组,里面的.+表示只有一个非\n字符。中间的.*用来匹配标签内的内容。/\2中,第一个斜杠与前面的html标签组成一对,/2表示引用第二个分组的内容。这里为什么要使用分组呢?因为我们还要保证html标签正确匹配。如果后面也使用.+,大家可以试着把/div和/body交换位置,表达式依旧匹配成功,但这显然不符合html的语法。

操作函数

​正则表达式的一些规则符号终于讲完了,最后再列举几个Python中操作正则表达式的函数:(re为导入的模块)

函数

作用

re.compile(patt)

封装正则表达式,并返回一个表达式对象

re.search(patt,str)

从左往右搜索第一个配正则表达式匹配的子字符串

re.findall(patt,str)

在字符串中查找正则表达式匹配到的所有子字符串,并返回一个列表

re.finditer(patt,str)

在字符串中查找正则表达式匹配到的所有子字符串,并返回一个Iterator对象

re.sub(patt,newstr,str)

将字符串中被正则表达式匹配到的子字符串替换成newstr,并返回新的字符串,原字符串不变

​Python的第一篇文章就到这里了。接下来会边学边写,做一些好玩的Python项目,再一起分享出来。如有错误,感谢指出!

参考资料:《Python 3快速入门与实战》

怎么用python骂人_人生苦短我用Python,本文助你快速入门相关推荐

  1. python词云图_人生苦短我用Python——词云图的绘制

    1.wordcloud库的安装 wordcloud库可以绘制词云,安装wordcloud库: pip install wordcloud 2.wordcloud库的介绍 wordcloud库的基本使用 ...

  2. 人生苦短我用python壁纸_人生苦短我用Python分分钟下载知乎美图给你看

    为什么说"人生苦短,我用python"? 为什么说人生苦短我用python Question 1 Python是什么 2 人们为什么用Python 3 Python是脚本语言吗 P ...

  3. python编程基础_月隐学python第2课

    python编程基础_月隐学python第2课 学习目标 掌握变量的输入和输出 掌握数据类型的基本概念 掌握算数运算 1.变量的输入和输出 1.1 变量输入 使用input输入 input用于输入数据 ...

  4. 查看Python的版本_查看当前安装Python的版本

    一.查看Python的版本_查看当前安装Python的版本 具体方法: 首先按[win+r]组合键打开运行: 然后输入cmd,点击[确定]: 最后执行[python --version]命令即可. 特 ...

  5. python骂人的程序_Python实现敏感词过滤的4种方法

    在我们生活中的一些场合经常会有一些不该出现的敏感词,我们通常会使用*去屏蔽它,例如:尼玛 -> **,一些骂人的敏感词和一些政治敏感词都不应该出现在一些公共场合中,这个时候我们就需要一定的手段去 ...

  6. python动态加载模块有什么用_人生苦短我用python(02)动态加载模块

    继第一期[人生苦短我用Python系列专栏]发布后,深受广大睿普迷的一致好评,经常问小普第二期什么时候出呀?好期待~ 来来来小普这就呈上第二期[02动态加载模块] 错过了第一期的小伙伴们可以点此穿越哦 ...

  7. python骂人脚本_Python 实现王者荣耀中的敏感词过滤示例

    王者荣耀的火爆就不用说了,但是一局中总会有那么几个挂机的,总能看到有些人在骂人,我们发现,当你输入一些常见的辱骂性词汇时,系统会自动将该词变成"*",作为python初学者,就想用 ...

  8. 人生苦短我学python表情包_人生苦短,我学PYTHON

    写程序开心吗?开心:).真的吗?作为一个想写好程序的手残加脑抽党,经常有人劝我,你并不适合当一个程序员,但是有时候又想在并不擅长的领域疯狂试探.以前学习C的时候,在算法的狂暴洗礼后,又要消灭比代码行还 ...

  9. python删除文件夹无法访问_人生苦短 我学Python——anaconda和Jupyter notebook安装使用...

    一.人生苦短 我学Python 为什么学习Python? 1.应用范围广 很多网站是用Python开发的,比如豆瓣,还有YouTube等等. 2.效率高,和其他编程语言对比,可以用少得多的代码写出相同 ...

  10. java手机代码骂人_好的代码会说话-代码整洁之道

    <代码整洁之道>总结 我们需要写出整洁的代码吗 我是个6年开发经验的java程序员,在我的职业生涯中,看到过不少让产生骂人冲动的代码,当然也写过让别人让别人想骂人的代码

最新文章

  1. 我今天的收获,必备stadio 插件
  2. 机器人组团到城市打工,第一站果然是赛博朋克城
  3. Python自动化测试 (九)urllib2 发送HTTP Request
  4. Data Augmentation
  5. 转载:C#正则表达式
  6. python elseif用法_Python关键字简介
  7. 2020年深圳杯数学建模竞赛A题
  8. vue使用echarts图表自适应的几种解决方案
  9. dubbo 监控中心配置
  10. OSI七层协议和Tcp/IP五层协议,路由器交换机和HUB的区别
  11. 微信公众号网页授权40029错误,小程序微信支付前后端逻辑? (微信授权支付之 (篇一))
  12. 12项信息安全标准发布 为解决车联网行业“顽疾”提供可靠指导
  13. Matlab 基础04 - 冒号Colon operator “:”的使用和复杂应用详析
  14. 微商软文标题怎么写才吸引人?
  15. 从你的全世界路过- 告白气球
  16. 小学奥数 7826 分苹果 python
  17. LK金字塔光流法与简单实现
  18. 机器人工程终身学习和工作计划-2022-
  19. 10000多套机械手毕业设计 课程设计 毕业论文 图纸 分享/上下料机械手、搬运机械手、苹果采摘机械手、液压机械手、三自由度机械手、水果采摘机械手、六自由度机械手、焊接机械手、码垛机械手、四自由……
  20. 计算机考研408每日一题 day135

热门文章

  1. 信息系统分析与设计 第十章 系统总体设计
  2. 如何提升原创文章排名与百度冰桶算法
  3. PIL库改变图片大小
  4. 《C++游戏编程入门 第四版》的例子Blackjack-
  5. 用无线局域网设置服务器,无线局域网如何配置
  6. 英语语法笔记——名词性从句(三)
  7. 2019矿大软件工程考试记录
  8. linux lighttpd,linux下lighttpd服务器的详细安装步骤 以及对flv流媒体的支持配置
  9. 嵌入式Linux设置开机自动运行程序(基于BusyBox init)
  10. 计算机本地网络给手机使用吗,电脑共享网络给手机用的方法步骤