Python 高级
同样还是学习@斌叔的程序媛课程的笔记~
第一第二第三课已经完成,第四课运行不成功(可能因为我用得是Python3, 斌叔用得是Python2吧)
---------------------------------------我是分割线-----------------------------------------------
第一课:
正则表达式:对字符串操作的一种逻辑公司(判断电话号码,邮箱等)
re模块
一般使用步骤是先把正则表达式的字符串换成Pattern 对象,接着用这个对象处理文本并得到匹配结果,最后根据结果信息,进行其他的操作
代码:(请参看注释)
import re #导入 re 模块
pattern = re.compile(r'Hello') #将正则表达式转换为 Pattern 对象
match = pattern.match('Hello cxy61!') #使用 pattern 匹配文本,获得结果,不匹配时结果为None
print(match) #输出匹配结果
if match:
print(match.group()) #输出分组信息
else:
print("No match.")
print (u"以上是匹配有结果的事例")
print (u"******************")
print (u"以下是无匹配结果的事例")
pattern2 = re.compile(r'Python')
match2 = pattern2.match('Hello cxy61')
print(match2)
if match2:
print(match2.group())
else:
print("No match.")
运行:
Screen Shot 2018-04-03 at 4.50.41 PM.png.pngmatch() 和 search() 对比
match() 只匹配字符串的起始,如果开始不匹配,便会返回 None,而 search() 是从头至尾对字符串进行匹配
Screen Shot 2018-04-03 at 5.01.11 PM.png.png
sub() 替换方法
import re
time = "2018-04-03"
pattern = re.compile(r'\D') # \D 表示匹配任意非数字
sub = pattern.sub("/",time) # sub(替换后的字符,要匹配的字符串)
print(sub)
print(re.sub(r'\D',"/",time)) # 也可以简写成这样
结果:2018/04/03
遇到问题:判断是否是电话号码时
issue : name 'raw_input' is not defined
python 3.0 之后已经用input代替了
import re
# 正则匹配电话号码
phone = input("phone number:")
pattern = re.compile('^0\d{2,3}\d{7,8}$|^1[3578]\d{9}$|^147\d{8}$')
match = pattern.match(phone)
if match:
print(match.group())
else:
print("error")
Screen Shot 2018-04-03 at 5.23.07 PM.png.png
正则表达式参考文档:http://www.regexlab.com/zh/regref.htm
第二课:数据库操作
要完成的任务如下:
Screen Shot 2018-04-04 at 11.25.15 AM.png.png在初级课程中,是以.TXT 格式存在了文件夹中,这次我们以数据库来进行保存
要用到 sqlit3 模块,它是Python 的内置模块,可以满足我们对数据的操作
import sqlite3
connect = sqlite3.connect("test_sqlite.db")
connect.close()
connect 后接数据库名称,若没有该数据库,则自动创建数据库,若存在该数据库,则链接数据库,再进行后续操作
你可以再运行前后使用 ls 命令查看当前文件目录,这个 test.db 就是刚创建的数据库
操作完数据库,要用 close() 方法关闭数据库,动手试试吧
上代码:
import sqlite3 #导入sqlite3 模块
connect = sqlite3.connect("test_sqlite.db") #创建数据库
cursor = connect.cursor() # 创建游标,以便用sql语句
创建一个名为diary的表,并设置一个ID 为自增主键,title,content 为text类型
cursor.execute("drop table diary")
cursor.execute("CREATE TABLE diary (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT , content TEXT)")
向表中插入数据,因为是自增主键,id可以写为NULL,表中id值会是1,2,3递增
cursor.execute("INSERT INTO diary VALUES (NULL,'title1','content1') ")
或者可以这样写
cursor.execute("INSERT INTO diary(title,content) VALUES ('title2','content2')")
查询表中所有数据,并输出
for row in cursor.execute("SELECT * FROM diary"):
print(row)
print(u"***** 增 ***** \n")
删除表中 id 为1的数据
cursor.execute("DELETE FROM diary WHERE id = 1")
在输出所有数据,以验证是否成功
for row in cursor.execute("SELECT * FROM diary"):
print(row)
print(u"***** 删 ***** \n")
修改 id 为2的数据
cursor.execute("UPDATE diary SET title = 'title0', content = 'content0' WHERE id = 2")
再输入所有数据,验证是否修改成功
for row in cursor.execute("SELECT * FROM diary"):
print(row)
print(u"***** 改 ***** \n")
#插入多条数据,供查看
items = [("title0","content0"),("title1","content1"),("title2","content2")]
#executeman 一次向标准插入多条数据
cursor.executemany("INSERT INTO diary(title,content) VALUES (?,?)",items)
print(u"插入多条数据后的表:")
for row in cursor.execute("SELECT * FROM diary"):
print(row)
#查
print(u"查 id 为5 的数据:")
cursor.execute("SELECT * FROM diary WHERE id = 5")
print(cursor.fetchall())
print(u"查 title 为 title0 的数据:")
cursor.execute("SELECT * FROM diary WHERE title = 'title0' ")
print(cursor.fetchall())
cursor.close() #关闭游标和数据库
connect.close()
运行结果:
Screen Shot 2018-04-06 at 11.25.25 AM.png.png小知识补充:
进行“查”操作时,fetchall() 方法可以得到符合条件的所有数据
表中数据除了主键值以外,其他键值是可以重复的
遇到issue:
cursor.execute("CREATE TABLE diary (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT , content TEXT)")
sqlite3.OperationalError: table diary already exists
解决方法:
在第八行前加入 ‘cursor.execute("drop table diary")’ 这句代码
解决方法来自torresFans的代码
继续学习:
一个数据库是可以创建多张表的,但是表名不能重复,如果重复将报错无法创建
如何解决这个问题呢?
首先我们先要获取当前数据库中所有的表,来看下面的代码
代码:
import sqlite3
connect = sqlite3.connect("test_sqlite.db")
cursor = connect.cursor()
cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
for item in cursor.fetchall():
print(item)
就可以读出之前创建的数据库所有的表了
Screen Shot 2018-04-06 at 3.22.41 PM.png.png
每个数据库中都有一个名为 sqlite_master 的内置表,它储存着所有的表信息,动手试试吧
Screen Shot 2018-04-09 at 11.00.23 AM.png.png从输出结果我们可以看到,每项都是一个元组,那么拿到表名只需要将输出改成这样即可
print item[0]
import sqlite3
connect = sqlite3.connect("test_sqlite.db")
cursor = connect.cursor()
# cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
# for item in cursor.fetchall():
# print(item)
#搜索表,若存在,则返回True, 反之返回 False
def searchTabel(str):
global cursor
flag = False
cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
for item in cursor.fetchall():
if item[0] == str:
flag = True
break
return flag
#创建表,若不存在,则创建,反之给出提示信息
def initTable(str):
global cursor
if searchTabel(str) == False:
sql = "create table",str,"(id INTEGER PRIMARY KEY AUTOINCREAMENT,tile TEXT,content TEXT)"
cursor.execute(sql)
else:
print(u"该表已存在")
initTable("diary")
我们一起把增删改查都写成函数的形式吧
多了一步操作, connect.commit()
这一步是对数据库操作事务的提交,之前没有加是为了方便程序的输出演示,在进行插入、修改和删除之后,要进行事务的提交.
这样才能真正的修改数据库中的数据,当然了查找操作就不必写了
根据 ID 删除数据,参数分别为表名(字符串类型),数据(元祖类型)
def inserData(name, tup):
global connect
global cursor
sql = "INSERT INTO " + name + "(title, content) VALUES (?,?)"
cursor.execute(sql, tup)
connect.commit()
根据 ID 删除数据,参数分别为表名(字符串类型),主键(整型)
def deleteData(name, id):
global connect
global cursor
sql = "DELETE FROM " + name + " WHERE id = " + str(id)
cursor.execute(sql)
connect.commit()
根据 ID 修改数据,参数分别为表名(字符串类型),主键(整型),数据(元祖类型)
def updateData(name, id, tup):
global connect
global cursor
sql = "UPDATE " + name + " SET title = '" + tup[0] + "', content = '" + tup[1] + "'WHERE id = " + str(id)
cursor.execute(sql)
connect.commit()
根据 id 查找数据,参数分别为表名(字符串类型),主键(整型)
def searchData(name, id):
global cursor
sql = "SELECT * FROM " + name + " WHERE id = " + str(id)
cursor.execute(sql)
print(u"查找的数据为:",cursor.fetchone())
注意:
SQL语句,衔接的时候一定要记得加空格!!!
使用:
# 向diary 表中插入数据 ('title1','title2')
inserData("diary",('title1','title2'))
# 删除 diary 表中id 为 5 的数据
deleteData("diary",5)
# 将 diary 表中 ID 为18 数据修改为 ('title100','content100')
updateData("diary",18,('title100','content100'))
# 查找 diary 中 id 为 10 的数据
第三课:网络编程
需要用到 socket
socket 是进程中的一种通信方式,可以用不同主机间的数据传输
Python中内置有socket模块,我们需要应用该模块的socket()方法创建一个队象,然后再进行设置
首先,新建一个server.py 文件作为我们的服务端
import socket
s = socket.socket() # 初始化 socket 对象
s.bind(('127.0.0.1',1234)) # 绑定端口号为 1234
s.listen(5) # 等待客户端连接
while True:
c, addr = s.accept() #客户端连接后,得到 connect 和 address
print(u"连接地址为:",addr)
c.send('成功连接至服务端。。。') # 向客户端发送消息
c.close() # 关闭连接
127.0.0.1 是我们的本地主机 IP,1234 是随意设置的一个端口号
Screen Shot 2018-04-09 at 12.16.51 PM.png.png可能出现的情况,已经标注了出来
lsof -i:1234
1234 是你设置的端口号,可以查看占用该端口号的进程
kill 80639
80639 是查到进程的 PID
遇到问题,如何杀死进程??
写入 kill 80639
好,运行成功后,这个终端不要关闭,再新打开一个终端,准备运行客户端
再新建一个 client.py 文件作为我们的客户端
import socket
s = socket.socket()
s.connect(('127.0.0.1',1234))
print(s.recv(1024))
s.close()
运行 client.py
遇到问题:c.send("成功连接至服务器。。。") # 向客户端发送消息
TypeError: a bytes-like object is required, not 'str'
这个send()方法不支持str,所以要把str 转为 bytes 类型
解决:‘c.send(bytes("成功连接至服务器。。。",encoding = "utf8")) ’
运行成功的截图:
Screen Shot 2018-04-11 at 2.32.31 PM.png.pngrecv(2014) 表示最多接受1024字节的数据
下面模拟以日记本为例子:
client.py
import socket
s = socket.socket()
s.connect(('127.0.0.1',1234))
print(s.recv(1024))
dict = {"title":"title","content":"content1"}
# 不能发生字典数据,所以转为字符串后发送
s.send(bytes(str(dict),encoding = "utf8"))
s.close()
server.py
import socket
s = socket.socket() # 初始化 socket 对象
s.bind(('127.0.0.1',1234)) # 绑定端口号为 1234
s.listen(5) # 等待客户端连接
while True:
c, addr = s.accept() #客户端连接后,得到 connect 和 address
print(u"连接地址为:",addr)
c.send(bytes("成功连接至服务器。。。",encoding = "utf8")) # 向客户端发送消息
# eval() 将字符串转换为字典
dict = eval(c.recv(1024))
if dict:
print(u"收到的数据为:",dict)
print(u"日记的标题为:",dict["title"])
print(u"日记的内容为:",dict["content"])
c.close() # 关闭连接
网友评论