内建模块

参考:BulidIn

日期


# 详细格式时间:datetime
# 注意到datetime是模块,datetime模块还包含一个datetime类.
from datetime import datetime ,timedelta,timezone

#获得当前时间
# 返回当前日期和时间,其类型是datetime。
current=datetime.now()
print(type(current),current)
# 自定义时间,不带时区,需要自己设置
current=datetime(2019,11,11,11,11,11,1111)
print(current)
# timestamp:把 1970年1月1日 00:00:00 UTC+00:00时区的时刻称为epoch time,记为0(1970年以前的时间timestamp为负数),
# 当前时间就是相对于epoch time(把epoch的时区转换为当地时区后做差)的秒数,称为timestamp。
# timestamp是一个浮点数。如果有小数位,小数位表示毫秒数。
# timestamp 是与时区无关的变量。
# datetime表示的时间需要时区信息才能确定一个特定的时间,否则只能视为本地时间。
# 如果要存储datetime,最佳方法是将其转换为timestamp再存储,因为timestamp的值与时区完全无关。
dt=current.timestamp()
print(dt)
#转换为当地时区
print(datetime.fromtimestamp(dt))
#转换为0时区标准时间。
print(datetime.utcfromtimestamp(dt))
# str<==>datetime
current = datetime.strptime('2019-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
print(current)
date_str=current.strftime('%Y-%I-%d %H:%M:%S %A')
print(date_str)

# 日期运算
current=current+timedelta(days=2,hours=5,minutes=4)
print(current)

# 时区转换
# 利用带时区的datetime,通过astimezone()方法,可以转换到任意时区。
#获得UTC 0
# 构建时区:timezone(timedelta(hours=8))
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt)
#转换为UTC 8
bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt)
# 不是必须从UTC+0:00时区转换到其他时区,任何带时区的datetime都可以正确转换
# 转换为UTC 9
tokyo_dt = bj_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt)

Collections

# namedtuple是一个函数,它用来创建一个自定义的tuple对象,并且规定了tuple元素的个数,
# 并可以用属性而不是索引来引用tuple的某个元素。
from collections import namedtuple, deque,OrderedDict,ChainMap,Counter
Point=namedtuple('Point',['x','y'])
point=Point(2,4)
print(point.x,point.y)
# 验证创建的Point对象是tuple的一种子类:
print(isinstance(point,tuple))

# 使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。
# deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈
# deque实现list的append()和pop(),appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素。
my_list=deque([1,2,3,4])
my_list.append(5)
my_list.appendleft(0)
print(my_list)
print(my_list.popleft(),my_list.pop())
print(my_list)

# 使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。
# 如果要保持Key的顺序,可以用OrderedDict
# OrderedDict的Key会按照插入的顺序排列,不是Key本身排序
my_dict=dict([('a', 1), ('b', 2), ('c', 3)])
print(my_dict)
my_dict=OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(my_dict)

# ChainMap可以把一组dict串起来并组成一个逻辑上的dict。
# ChainMap本身也是一个dict,但是查找的时候,会按照顺序在内部的dict依次查找。
# combine_dict=ChainMap(dict_0, dict_1, dict_1)
# 顺序:dict_0->dicy_1->dict_2
# value=combine_dict['key']

# Chainmap 环境参数,默认参数,命令行参数:组合可实现多参数输入

# 解析命令行参数
import os, argparse
# 解析对象
parser = argparse.ArgumentParser()
# python file.py  -u bob => user=bob
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
# 构建参数字典 (v非空)
command_line_args = { k: v for k, v in vars(namespace).items() if v }

# 环境变量
# user=bob python file.py
# 环境参数字典
env_args_dict=os.environ

# Counter是一个简单的计数器,例如,统计字符出现的个数:

counter=Counter()
for ch in 'fuck you leather man!':
    counter[ch]=counter[ch]+1
print(counter)

Hash校验

# 摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
# 摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。

import hashlib

# MD5算法:生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?'.encode('utf-8'))
# 多次添加消息
md5.update('fuck'.encode('UTF-8'))
print(md5.hexdigest())

#sha1 :结果是160 bit字节,通常用一个40位的16进制字符串表示。
sha1 = hashlib.sha1()
sha1.update('how to use sha1 in '.encode('utf-8'))
# 多次添加消息
sha1.update('python hashlib?'.encode('utf-8'))
print(sha1.hexdigest())

# 在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,
# 加salt的哈希就是:计算一段message的哈希时,根据不通口令计算出不同的哈希。要验证哈希值,必须同时提供正确的口令。
# Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1
import hmac
import random
# 传入的key和message都是bytes类型,str类型需要首先编码为bytes
msg=b'fuck'
key=(''.join([chr(random.randint(48, 122)) for i in range(20)])).encode('utf-8')
#h=hmac.new(key,msg,digestmod='MD5')
h=hmac.new(key,msg,digestmod='sha1')
# 多次添加消息
h.update('lether man'.encode('utf-8'))
print(h.hexdigest())

Base64 转换

# Base64是一种用64个字符来表示任意二进制数据的方法。
# 首先,准备一个包含64个字符的数组,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit,划为4组,每组正好6个bit,2^6=64
# 得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。
# Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,
# 如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节,
# Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。

import base64
msg=b'fuck you leather man!'
print(msg)
code_msg=base64.b64encode(msg)
print(code_msg)
decode_mag=base64.b64decode(code_msg)
print(decode_mag)

# 由于标准的Base64编码后可能出现字符+和/,在URL中就不能直接作为参数,
# 所以又有一种"url safe"的base64编码,其实就是把字符+和/分别变成-和_

code_msg=base64.urlsafe_b64encode(msg)
print(code_msg)
decode_mag=base64.urlsafe_b64decode(code_msg)
print(decode_mag)

#由于=字符也可能出现在Base64编码中,但=用在URL、Cookie里面会造成歧义,所以,很多Base64编码后会把=去掉
#因为Base64是把3个字节变为4个字节,=号为尾部补全内容,所以,Base64编码的长度永远是4的倍数,因此,需要加上=把Base64字符串的长度变为4的倍数,就可以正常解码了

struct 二进制转换

# struct模块来解决bytes和其他二进制数据类型的转换
import struct

# struct的pack函数把任意数据类型变成bytes
# >表示字节顺序是big-endian,也就是网络序,
# ? :bool   1
# c :char   1  b :unsigned char 1
# h :short  2  H :unsigned short 2
# i :int    4  I :unsigned int 4
# l :long   4  L :unsigned long 4
# f :float  4
# d :double 8

byte_data=struct.pack('>IH', 102400,99)
# unpack把bytes变成相应的数据类型:
data=struct.unpack('>IH', byte_data)
print(data)

Contex

# Python的with语句允许我们非常方便地使用资源,而不必担心资源没有关闭
# 实际上,任何对象,只要正确实现了上下文管理,就可以用于with语句
# with语句不仅可以管理文件,还可以管理锁、连接等等

# import  threading
# lock = threading.lock()
# with lock:
#     #执行一些操作
#     pass

# 实现上下文管理是通过__enter__和__exit__这两个方法实现的

# with语句中的[as variable]是可选的,如果指定了as variable说明符,则variable是上下文管理器expression调用__enter__()函数返回的对象。
# 所以,f并不一定就是expression,而是expression.__enter__()的返回值
# def __enter__(self):
#     print('Begin')
#     return self
#
# 分别为异常类型、异常信息和堆栈
# def __exit__(self, exc_type, exc_value, traceback):
#     if exc_type:
#         print('Error')
#     else:
#         print('End')

# @contextmanager 实现上下文管理

from contextlib import contextmanager
# 自定义类
class MyClass(object):
    def __init__(self,name):
        self.__name=name
    def tell(self):
        return self.__name
    def close(self):
        print('closed')
# 管理器
@contextmanager
def manager(name):
    # yield之前的代码等同于上下文管理器中的__enter__函数。
    print('begin')
    # yield的返回值等同于__enter__函数
    try:
        yield MyClass(name)
    except:
        pass
    # 等同于上下文管理器的__exit__函数
    print('end')
# print('begin')==> print(man.tell())==> print('end')
with manager('fuck you') as man:
    print(man.tell())

# 我们希望在某段代码执行前后自动执行特定代码,也可以用@contextmanager实现

@contextmanager
def manager():
    print('begin')
    yield
    print('end')
# print('begin')==> print('do something')==> print('end')
with manager() :
    print('do something')

# 如果一个对象没有实现上下文,我们就不能把它用于with语句。可以用closing()来把该对象变为上下文对象。
# 它的作用就是把任意对象变为上下文对象,并支持with语句。
# closeing上下文管理器仅使用于具有close()方法的资源对象
from contextlib import closing
# print(myclass.tell())===>myclass.close()
with closing(MyClass('hello world')) as myclass:
    print(myclass.tell())

Itertools

import  itertools

# count()会创建一个无限的迭代器,
# 所以上述代码会打印出自然数序列,根本停不下来,
counts=itertools.count(2)
print(type(counts))
for item in counts:
    print(item)

# repeat()负责把一个元素无限重复下去,不过如果提供第二个参数就可以限定重复次数
repeats=itertools.repeat('msg',10)
print(type(repeats))
for item in repeats:
    print(item)

# 通过takewhile()等函数根据条件判断来截取出一个有限的序列
counts=itertools.takewhile(lambda x:x<15,counts)
print(list(counts))

# chain()可以把一组迭代对象串联起来,形成一个更大的迭代器
for item in itertools.chain('fuck','you'):
    print(item)


def pi(n):
    counts=list(map(lambda x:4/((-1)**(1+x)*(2*x-1)),itertools.takewhile(lambda x:x<n+1,  itertools.count(1))))
    return sum(counts)

assert 3.04 < pi(10) < 3.05
assert 3.13 < pi(100) < 3.14
assert 3.140 < pi(1000) < 3.141
assert 3.1414 < pi(10000) < 3.1415
print('ok')

Urllib

from urllib import request, parse

# 模拟浏览器发送GET请求,就需要使用Request对象,通过往Request对象添加HTTP头,我们就可以把请求伪装成浏览器。
req = request.Request('http://www.douban.com/')
# 添加Http请求头
req.add_header('User-Agent',
               'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.16 Safari/537.36 Edg/79.0.309.12')

with request.urlopen(req) as f:
    print('Status:', f.status, f.reason)
    # 获取Http请求头
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:\n', f.read().decode('utf-8'))
    htmls = f.read().decode('utf-8')

# 操作XML有两种方法:DOM和SAX。DOM会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。
# SAX是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件
# 使用SAX解析XML事件是start_element,end_element和char_data

# SAX模式
from xml.parsers.expat import ParserCreate

class DefaultSaxHandler(object):
    # 解析起始标签<a href="/python"> ===> name=a ,attrs: {'href': '/python'}
    def start_element(self, name, attrs):
        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))

    # 解析终止标签
    def end_element(self, name):
        print('sax:end_element: %s' % name)

    # 解析内容
    def char_data(self, text):
        print('sax:char_data: %s' % text)

xml = r'''<?xml version="1.0"?>
<ol>
    <li><a href="/python">Python</a></li>
    <li><a href="/ruby">Ruby</a></li>
</ol>
'''
# 绑定事件
handler = DefaultSaxHandler()
parser = ParserCreate()
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
# 开始解析,碰到一个标签就开始调用相应函数,嵌套解析内容
parser.Parse(xml)

# 解析html
from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    # # 解析起始标签<a href="/python"> ===> name=a ,attrs: {'href': '/python'}
    def handle_starttag(self, tag, attrs):
        print('starttag-----------------------------------')
        print('<%s>' % tag)

    # 解析终止标签
    def handle_endtag(self, tag):
        print('endtag-----------------------------------')
        print('</%s>' % tag)

    def handle_startendtag(self, tag, attrs):
        print('startendtag-----------------------------------')
        print('<%s/>' % tag)

    # 解析内容
    def handle_data(self, data):
        print('data-----------------------------------')
        print(data)

    # 解析注释
    def handle_comment(self, data):
        print('commit-----------------------------------')
        print('<!--', data, '-->')

    def handle_entityref(self, name):
        print('entityref-----------------------------------')
        print('&%s;' % name)

    def handle_charref(self, name):
        print('charref-----------------------------------')
        print('&#%s;' % name)

parser = MyHTMLParser()
# feed()方法可以多次调用。碰到一个标签就开始调用相应函数,嵌套解析内容
parser.feed(htmls)

猜你喜欢

转载自www.cnblogs.com/huangqiang97/p/11839194.html