<jupyter_start><jupyter_text>递归回溯法：叫称为试探法，按选优条件向前搜索，当搜索到某一步，发现原先选择并不优或不达到目的时，就退回一步重新选择经典问题：骑士巡逻<jupyter_code>import os
import sys
import time
SIZE = 5
total = 0
def print_board(board):
    for row in board:
        for col in row:
            print(str(col).center(4),end='')
        print()
        
def patrol(board,row,col,step=1):
    if row >= 0 and row <SIZE and \
        col >= 0 and col <SIZE and \
        board[row][col] == 0:
            board[row][col] = step
            if step ==SIZE * SIZE:
                global total
                total += 1
                print(f'第{total}种走法：')
                print_board(board)
            patrol(board, row - 2, col - 1, step + 1)
            patrol(board, row - 1, col - 2, step + 1)
            patrol(board, row + 1, col - 2, step + 1)
            patrol(board, row + 2, col - 1, step + 1)
            patrol(board, row + 2, col + 1, step + 1)
            patrol(board, row + 1, col + 2, step + 1)
            patrol(board, row - 1, col + 2, step + 1)
            patrol(board, row - 2, col + 1, step + 1)
            board[row][col] = 0
            
def main():
    board = [[0] * SIZE for _ in range(SIZE)]
    patrol(board,SIZE - 1,SIZE - 1)
    
    
if __name__ == '__main__':
    main()<jupyter_output>第1种走法：
 23  12  3   18  25 
 4   17  24  13  8  
 11  22  7   2   19 
 16  5   20  9   14 
 21  10  15  6   1  
第2种走法：
 23  14  3   8   25 
 4   9   24  13  16 
 19  22  15  2   7  
 10  5   20  17  12 
 21  18  11  6   1  
第3种走法：
 23  18  3   8   25 
 4   9   24  19  14 
 17  22  13  2   7  
 10  5   20  15  12 
 21  16  11  6   1  
第4种走法：
 23  14  3   8   25 
 4   19  24  15  10 
 13  22  9   2   7  
 18  5   20  11  16 
 21  12  17  6   1  
第5种走法：
 23  8   3   14  25 
 10  15  24  19  4  
 7   22  9   2   13 
 16  11  20  5   18 
 21  6   17  12  1  
第6种走法：
 23  8   3   18  25 
 14  19  24  9   4  
 7   22  13  2   17 
 12  15  20  5   10 
 21  6   11  16  1  
第7种走法：
 23  8   3   14  25 
 16  13  24  9   4  
 7   22  15  2   19 
 12  17  20  5   10 
 21  6   11  18  1  
第8种走法：
 23  18  3   12  25 
 8   13  24  17  4  
 19  22  7   2   11 
 14  9   20  5   16 
 21  6   15  10  1  
第9种走法：
 23  8   13  18  25 
 14  3   24  7   12 
 9   22  17  2   19 
 4   15  20  11  6  
 21  10  5   [...]<jupyter_text>序列化和反序列化序列化 - 将对象变成字节序列(bytes)或者字符序列(str) - 串行化/腌咸菜反序列化 - 把字节序列或者字符序列还原成对象Python标准库对序列化的支持：json - 字符形式的序列化pickle - 字节形式的序列化 哈希摘要 - 数字签名/指纹 - 单向哈希函数<jupyter_code>class StreamHasher():
    """摘要生成器"""
    def __init__(self,algorithm='md5',size=4096):
        """初始化方法
        @params:
            algorithm - 哈希摘要算法
            size - 每次读取数据的大小
        """ 
        self.size = size
        cls = getattr(__import__('hashlib'),algorithm.lower())
        self.hasher = cls()
        
        
        
    def digest(self,file_stream):
        """生成器十六进制的摘要字符串"""
        for data in iter(lambda:file_stream.read(self.size),b''):
            self.hasher.update(data)
        return self.hasher.hexdigest()
    
    
    def __call__(self,file_stream):
        return self.digest(file_stream)
    
    
def main():
    """主函数"""
    hasher1 = StreamHasher()
    hasher2 = StreamHasher('sha1')
    hasher3 = StreamHasher('sha256')
    with open('C:\\Users\\a\\Desktop\\as.txt', 'rb') as file_stream:
        print(hasher1.digest(file_stream))
        file_stream.seek(0, 0)
        print(hasher2.digest(file_stream))
        file_stream.seek(0, 0)
        print(hasher3(file_stream))


if __name__ == '__main__':
    main()
加密和解密
对称加密 - 加密和解密是同一个密钥 - DES / AES
非对称加密 - 加密和解密是不同的密钥 - RSA
import base64
from hashlib import md5
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.PublicKey import RSA
def main():
    """主函数"""
    # 生成密钥对
    key_pair = RSA.generate(1024)
    # 导入公钥
    pub_key = RSA.importKey(key_pair.publickey().exportKey())
    # 导入私钥
    pri_key = RSA.importKey(key_pair.exportKey())
    message1 = 'hello, world!'
    # 加密数据
    data = pub_key.encrypt(message1.encode(), None)
    # 对加密数据进行BASE64编码
    message2 = base64.b64encode(data[0])
    print(message2)
    # 对加密数据进行BASE64解码
    data = base64.b64decode(message2)
    # 解密数据
    message3 = pri_key.decrypt(data)
    print(message3.decode())



if __name__ == '__main__':
    main()<jupyter_output>b'YFLP5z4AkRTxFBwD9Je7trrgue3aKs9xmf/7BGNDWhzD068JcMvltDXXup0zcIDPwtW8t8aty6PvQxOTQY2xSPYuLPvV1wiinoGw/K4jKnPP8AaGhI6K8HXItw4RB02+kdwB/+kLpGAFRpeBPHoytLbfnkeBdUPgb5XDOGvo3TU='
hello, world!<jupyter_text>装饰器 - 装饰器中放置的通常都是横切关注（cross-concern）功能所谓横切关注功能就是很多地方都会用到但跟正常业务又逻辑没有必然联系的功能装饰器实际上是实现了设计模式中的代理模式 - AOP（面向切面编程）<jupyter_code>from functools import wraps
from random import randint
from time import time, sleep
import pymysql
def record(output):

    def decorate(func):

        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time()
            ret_value = func(*args, **kwargs)
            output(func.__name__, time() - start)
            return ret_value

        return wrapper

    return decorate


def output_to_console(fname, duration):
    print('%s: %.3f秒' % (fname, duration))


def output_to_file(fname, duration):
    with open('log.txt', 'a') as file_stream:
        file_stream.write('%s: %.3f秒\n' % (fname, duration))


def output_to_db(fname, duration):
    con = pymysql.connect(host='localhost', port=3306,
                          database='test', charset='utf8',
                          user='root', password='<PASSWORD>',
                          autocommit=True)
    try:
        with con.cursor() as cursor:
            cursor.execute('insert into tb_record values (default, %s, %s)',
                           (fname, '%.3f' % duration))
    finally:
        con.close()


@record(output_to_console)
def random_delay(min, max):
    sleep(randint(min, max))


def main():
    for _ in range(3):
        # print(random_delay.__name__)
        random_delay(3, 5)
    


if __name__ == '__main__':
    main()<jupyter_output>random_delay: 4.000秒
random_delay: 4.000秒
random_delay: 5.000秒<jupyter_text>装饰类的装饰器 - 单例模式 - 一个类只能创建出唯一的对象上下文语法：__enter__ / __exit__<jupyter_code>import threading
from functools import wraps
def singleton(cls):
    """单例装饰器"""
    instances = {}
    lock = threading.Lock()

    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instances:
            with lock:
                if cls not in instances:
                    instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return wrapper


@singleton
class President():

    def __init__(self, name, country):
        self.name = name
        self.country = country

    def __str__(self):
        return f'{self.country}: {self.name}'


def main():
    print(President.__name__)
    p1 = President('特朗普', '美国')
    p2 = President('奥巴马', '美国')
    print(p1 == p2)
    print(p1)
    print(p2)


if __name__ == '__main__':
    main()<jupyter_output>President
True
美国: 特朗普
美国: 特朗普
{'fraction_non_alphanumeric': 0.10870193697600462, 'fraction_numerical': 0.07386527898236485, 'mean_word_length': 2.0333187198597105, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '12937', 'license': 'Apache-2.0', 'n_tokens_mistral': 3192, 'n_tokens_neox': 3018, 'n_words': 664, 'path': 'Day16_5.ipynb', 'repo_name': 'hdbnl1122/python100', 'size': '6914'}