[读书笔记] Python语言及其应用

记录下秋招期间看的一本Python工具书《Python语言与其应用》,查漏补缺,部分内容整理如下:

  1. 易混淆概念
    1.1 删除 - del,remove()和pop()
    1.2 复制 - 浅/深复制
    1.3 容器 - 列表、元组、字典和集合
    1.4 日期时间 - datetime
  2. 代码结构
    2.1 形参与位参
    2.2 生成器
    2.3 装饰器
    2.4 包
    2.5 对象与类
  3. 数据
    3.1 字符串
    3.2 数据读写
    3.3 数据库
  4. Web
  5. 系统
  6. 开发
    6.1 并发
    6.2 测试

1. 易混淆概念

1.1 删除 - del,remove()和pop()

对于列表,有三种删除方法,分别是del,remove()和pop()。下面以a = ['a', 'a', 'b', 'c', 'd'] 为例。

方法 区别 代码 结果
del 删除指定位置的元素
del a[-1]
a = ['a', 'b', 'c']
remove() 删除具有指定值的元素
a.remove('a')
a = [ 'b', 'c', 'd']
pop() 获取并删除指定位置的元素
a.pop(1)
a =  ['a', 'b', 'c', 'd']

 

 

 

 

 

 

 

 

1.2 复制 - 浅/深复制

如果将一个列表赋值给多个变量,改变其中原列表任何一处会造成其它其它复制变量对应的值也被修改。要改进实现真正独立的复制变量,要是使用深复制方法。

  • 如果是简单对象,例如:a=[1,2,3] 这样里面没有嵌套子对象的话,一般用系统自带的a.copy或者import copy然后copy.copy(a)就能实现浅复制
  • 但如果是复杂对象,例如:a=[1,2,3, [2,'a']] 这样含有子对象的话,需要使用copy模块的copy.deepcopy(a)来实现深复制,简单来说就是深度复制列表里的其它子对象。

 

1.3 容器 - 列表、元组、字典和集合

Python里的容器有列表、元组、字典和集合。

容器 区别  方法 
列表  顺序、数据类型可变,允许元素重复,可变对象 list() 
元组   顺序、数据类型可变,不允许元素重复,不可变对象 ()
字典   键值对,键不可变,值可变 {} 
集合  数据类型可变,有顺序,不允许元素重复,可变对象 set(())

 

 

 

 

 

 

 

1.4 日期时间

Python关于时间模块有两个(datetime模块和time模块),这里主要介绍datetime模块,它定义了4个主要对象。

  • date处理日期(年月日)
  • time处理时间(时分秒和微秒)
  • datetime处理日期时间同时出现情况
  • timedelta处理日期和/或时间间隔
from datetime import date
a = date(2019, 9, 28)

from datetime import time
noon = time(12,0,0)

a.day
a.month
a.year 

a.isoformat() # 打印一个date对象

# date的加法
one_day = timedelta(days=1)
yesterday = a - one_day

now = datetime.now() # 获取当地日期和时间

 strftime()可以把日期时间转换字符串。

import time

t = date(2014, 2, 4)
print(time.strftime("%Y:%M:%d", t))

# 或者
t.strftime(fmt)

 

2. 代码结构

2.1 形参与位参

位置参数适合函数输入参数比较少,形参适合函数输入参数多的时候。一般模型超参数多的时候,适合使用一个参数字典搭配形参来使用。

#位置参数:*操作符
a = (2,3)
print pow(*a)
#这里将a的内容根据现有的位置放入了幂函数里面,即pow(2,3)
 
#命名参数:**操作符
a_dict = {"x":10,"y":20}
def dist(x,y)
    return abs(x-y)
 
print dist(**a_dict)
#这里键值对应,把值传入了命名的参数里面,最后放入函数dist中

 

2.2 生成器

生成器就是迭代器产生数据,相当于for循环里的range()。

# 步骤1:先编写一个range()函数版本
def my_range(first=0, last=10, step=1):
    number = first
    while number < last:
        yield number # 生成器输出
        number += step

# 步骤2:返回一个生成器对象
ranger = my_range(1,5)

# 步骤3:对这个生成器对象进行迭代
for x in ranger:
    print(x)

 

2.3 装饰器

简单来说,装饰器相当于一个公共函数。@语法只是将函数传入装饰器函数。

# 步骤1:定义装饰器函数
def log(func):
    def wrapper(*args, **kwargs):
        print('call %s():' % func.__name__)
        print('args = {}'.format(*args))
        return func(*args, **kwargs)

    return wrapper

# 步骤2:使用@调用装饰器,@下面的函数是闭包,会被放入装饰器函数里
@log
def test(p):
    print(test.__name__ + " param: " + p)
    
test("I'm a param")

# 其实装饰器的使用相当于下面这种函数调用方法
def test(p):
    print(test.__name__ + " param: " + p)

wrapper = log(test)
wrapper("I'm a param")

用例来源:https://www.jianshu.com/p/ee82b941772a

 

2.4 包

有时候模型设计的时候有很多不同的自定义函数,但你想把他们作为模块导入另一个文件当中。比如一个空白文档你想导入你另一个自定义函数文件sources,例如:from sources import daily, weekly。要实现这个功能,得再sources目录下添加一个文件:__init__.py。这个文件可以是空的。

 

2.5 对象和类

  • 对象:对象既包含数据(变量,即特性,attribute),也包含代码(函数,也称为方法)。
  • 类:如果把对象比作塑料盒子,类则像是制作盒子用的模具。
class Person():
    def __init__(self, name):
        self.name = name

继承:保有原有类不动的情况下,进行新类上的操作。

# 父类
class
Car(): pass
# 继承的子类 class Yugo(Car): pass

 如果在Yugo里直接定义其它函数,会直接覆盖掉Car里的原有函数。而且在子类中定义__init__()方法时,父类的__init__()方法会被覆盖。因此,在子类中,父类的初始化方法并不会被自动调用,我们必须显示的调用它。例如下面的方法:

class EmailPerson(Person):
    def __init__(self, name, email):
        super().__init__(name)
        self.email = email

 

 3. 数据

3.1 字符串

计算机的基本存储单元是字节(btye),它包含8位/比特(bit)- Unicode字符串特点,可以存储256种不同的值(每位0/1可能取值)。ASCII只使用了7位(128种取值):26个大写字母、26个小写字母、10阿拉伯数字、一些标点符号、空白符以及一些不可打印的控制符。如果你创建的Python字符串时使用了从别的文本源(例如网页)复制粘贴过来的字符串,一定要确保文本源使用的时UTF-8编码。将Latin-1或者Windows1252复制粘贴为Python字符串的错误是极其常见的,这样得到的字节序列是无效的,会产生许多后续隐患。

 

3.2 数据读写

打开文件输入的mode包含两个字母:对文件的操作+文件的类型。

mode的第一个字母 - 操作

  • r: 读。
  • w: 写。如果文件不存在,则新建立。如果存在则重写新内容。
  • x: 表示在文件不存在的情况下新创建并写文件。
  • a: 如果文件存在,在文件末尾追加写内容。

mode的第二个字母 - 文件类型

  • t: (或者省略)代表文本类型。
  • b: 代表二进制文件。

 

写入文件有下列两种方式:

# 方法1:需要额外的关闭文件
a = 'alvin'
fileobj = open('filename', 'mode') # 打开
fileobj.write(alvin) # 写入
fileobj.close() # 关闭

# 方法2:自动关闭文件
with open('filename', 'mode') as f:
    f.write(a)

读取文件时有三种方法:分块输入,单行读取输入,迭代单行输入。

# 方法1:分块输入
poem = ''
fin = open('alvin', rt'')
chunk = 100 # 设置单次读取的行数
while True:
    fragment = fin.read(chunk)
    if not fragment: # 如果为空
        break
    poem += fragment

fin.close()


# 方法2:单行读取输入
poem = ''
fin = open('alvin', rt'')
while True:
    fragment = fin.readline() # 单行读取
    if not line: # 如果为空
        break
    poem += line

fin.close()

# 方法3:迭代单行读取(更加简洁)
poem = ''
fin = open('alvin', rt'')
for line in fin:
    poem += line

fin.close()

 

3.3 数据库

DB-API是Python中访问关系型数据库的标准API,使用它可以必须简单的程序来处理多种类型的关系型数据库。主要函数如下:

  • connect(): 连接数据库,包含参数用户名、密码、服务器地址等。
  • cursor(): 创建一个cursor对象来管理查询。
  • execute()executemany(): 对数据库执行一个或多个SQL命令。
  • fetchone()、fetchmany()fetchall(): 得到execute之后的结果。

下面以连接轻量级SQLite数据库为例:

import sqlite3
conn = sqlite3.connect('alvin.db') # 连接数据库
curs = conn.cursor() # 创建一个语句
curs.execute('''CREATE TABLE zoo
(critter CARCHAR(20) PRIMARY KEY,
count INT,
damage FLOAT)''') # 建立数据库

# 插入数据
ins = 'INSERT INTO zoo (critter, count, damage) VALUES(?, ?, ?)'
curs.execute(ins, ('weasel', 1, 2000, 0))

# 获取结果
r = curs.fetchall()
print(r)

# 关闭查询语句和数据库
curs.close()
conn.close()

 

4. Web

在Python中,Web客户端和服务器模块主要是三个包:http, urllib和requests。

  • http会处理所有客户端-服务器HTTP请求的具体细节:
  • client: 会处理客户端的部分。
  • server: 会协助你编写Python Web服务器程序。
  • cookies和cookiejar会处理cookie,cookie可以在请求中存储数据。

urllibs是基于http的高层库:

  • request: 处理客户端请求。
  • response: 处理服务端的响应。
  • parse: 会解析URL。

获取网站内容:

import urllib.request as ur
url = 'http://www.iheartquotes.com/api/v1/random'
conn = ur.urlopen(url) # 打开
data = conn.read() # 读取
print(data) # 输出

print(conn.status)

上面打印的HTTP状态码表示了网站响应情况:

  • 1xx(信息):服务器收到了请求,但需要客户端发送一些额外的信息。
  • 2xx(成功):请求成功。除了200以外,其它的状态码还会包含一些特殊含义。
  • 3xx(重定向):资源位置发生改变,所以响应会返回一个新的URL给客户端。
  • 4xx(客户端错误):客户端发生错误,最出名的404(网页不存在)。
  • 5xx(服务端错误):500是最常见的错误。502是网关错误。

requests模块更短和简洁:

import requests
url = '...'
resp = requests.get(url)
print(resp)

 

5. 系统

Python在模块os(操作系统,operating system)中提供了许多系统函数。

import os

os.path.exists('alvin.txt') # 检查文件/目录是否存在

os.path.isfile('alvin.txt') # 检查是否为文件
os.path.isdir('alvin.txt')

os.rename('a.txt', 'b.txt') # 把a.txt重命名为b.txt

os.remove('a.txt) # 删除文件

os.mkdir('poems') # 创建目录
os.rmdir('poems') # 删除目录

import  shutil
shutil.copy('a.txt', 'b.txt') # 把a.txt复制到b.txt

import glob
glob.glob('m*') # 获取所有以m开头的文件和目录

在使用isfile()等与路径相关函数时,一个点号(.)表示当前目录,两个点号(..)表示上层目录。

在使用glob()列出匹配文件时,*代表任意名称。?会匹配一个字符。[abc]会匹配字符a/b/c。[!abc]匹配除了a/b/c之外的所有字符。例如'[abc]*e'表示获取以a/b/c开头且以e结尾的文件和目录。

 

6. 开发

6.1 并发

与并发相关的两个术语:同步和异步。

  • 同步:一件事接着一件事发生。例如:工人等着处理盘子,处理完给下一个人。
  • 异步:任务相互独立。例如:盘子推在两个人中间。

有两个模块经常会被用到:multiprocessing(进程)和threading(线程)。线程运行在进程内部,他们的区别在于threading没有terminate()函数。很难终止一个正在运作的线程,因为这可能会引起代码和时空连续性上的各种问题。但没有全局变量时,线程是非常有用并且安全的。

 

6.2 测试

比较流行的检查模块有pylint和pyflakes,他们可以检查代码错误和代码风格问题。而unittest模块是用作测试的。

 

posted @ 2019-09-29 11:24  Alvin_Ai  阅读(431)  评论(0)    收藏  举报