开发知识点-Python从小白到入土

在这里插入图片描述

Python从小白到入土

PYTHON介绍以及应用场景

安装 3.7.6 3.11.8

https://www.python.org/downloads/
https://www.python.org/downloads/release/python-376/

Windows x86-64 executable installer

产品营销

Mirai

https://wiki.mrxiaom.top/mirai/
https://blog.csdn.net/m0_60496544/article/details/135588047

WeChatPYAPI

https://gitee.com/mrsanshui/WeChatPYAPI

wxpy

https://gitee.com/freedom_pioneer/wxpy

itchat

https://gitee.com/CharlesInOSC/itchat

tkinter

https://www.jb51.net/python/2944274ct.htm

按钮

https://blog.csdn.net/jzwalliser/article/details/128344943

matplotlib 常用图形

https://blog.csdn.net/senlin_6688/article/details/135484368

pyqt5构建股票交易北向资金

https://blog.csdn.net/liyuanjinglyj/article/details/113755633


pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple

https://blog.csdn.net/liyuanjinglyj/category_10746057.html

Python_实现_股票量化_交易学习进阶

https://blog.csdn.net/u011930054/article/details/112944314

python量化股票市场情绪指标ARBR

https://zhuanlan.zhihu.com/p/61488013
https://blog.csdn.net/belldeep/article/details/123442192

Python量化–基于机器学习的回测:预测股价走势

https://zhuanlan.zhihu.com/p/669215299

python BRAR 指标计算 import akshare



python3所需要的组件

yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make wget libffi-devel


备份现有的python2

cd /usr/bin

mv python python.bak

mv pip pip.bak


/usr/bin/pip3.6 install dingtalkchatbot -i https://pypi.tuna.tsinghua.edu.cn/simple

/usr/bin/pip3.6 install akshare --upgrade --user -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install schedule -i https://pypi.tuna.tsinghua.edu.cn/simple

第一个PYTHON程序

Py 远程控制

python -m pip install websockets -i "https://pypi.doubanio.com/simple/"
websocket

python -m pip install pyautogui -i "https://pypi.doubanio.com/simple/"

python -m pip install websocket-client  -i "https://pypi.doubanio.com/simple/"





https://blog.csdn.net/cj_Allen/article/details/104403103
reGeorg+Proxifier内网代理以及远程连接内网服务器


frp 和 reGeorg 是两种不同的工具,分别用于实现内网穿透和 Web 服务隧道代理。它们有以下几点区别:

功能不同:frp 主要用于内网穿透,支持 TCP/UDP 流量转发和 HTTP/WebSocket 反向代理等功能;而 reGeorg 主要用于 Web 服务隧道代理,通过 HTTP 协议将 TCP 流量转发到另一个端点。

实现方式不同:frp 使用了自定义的协议和客户端/服务器模式,通过配置文件来管理不同的服务和通道;而 reGeorg 基于 HTTP 协议和反向代理技术实现,使用 PHP/C# 等语言编写的代理程序作为客户端,将 TCP 流量封装到 HTTP 数据包中,再传输到另一个代理程序或主机上。

应用场景不同:frp 适用于需要在公网上访问内网服务或应用的场景,如远程控制、文件共享、应用发布等;而 reGeorg 更多用于绕过网络防火墙限制访问外部资源或服务的场景,如访问 Google、Twitter 等被屏蔽的网站或服务,或将内网 Web 应用映射到 Internet 上进行漏洞测试等。





ACL(Access Control List)是一种访问控制列表,用于定义和实施对资源的访问权限。ACL 策略可以帮助组织和管理者控制谁可以访问特定的资源以及以何种方式进行访问。以下是一些常见的 ACL 策略:

黑名单策略:黑名单策略是指禁止访问某些特定资源或执行某些特定操作。在 ACL 中,您可以列出需要被禁止的用户、IP 或其他标识符,从而限制他们的访问权限。

白名单策略:白名单策略是指只允许特定的用户、IP 或其他标识符进行访问或执行特定操作。您可以列出允许访问的资源或操作,其他未被列出的都将被禁止。

角色基础的访问控制策略:这种策略基于角色来管理资源的访问权限。每个用户都会分配一个或多个角色,而每个角色都有一组特定的权限。通过将用户与角色关联起来,并授予或撤销角色相应的权限,可以实现灵活且可扩展的访问控制。

基于属性的访问控制策略:这种策略基于资源或用户的属性来决定访问权限。例如,可以设置只有具有特定标签或属性的用户可以访问某些敏感数据。

时间限制策略:时间限制策略基于时间条件控制资源的访问权限。您可以定义在特定时间段内允许或禁止对资源的访问。

审计日志策略:审计日志策略是指记录和审核对资源访问的日志记录。通过日志记录,可以追踪和监控谁访问了资源、何时访问以及执行了哪些操作。

Gui

GUI是Graphical User Interface(图形用户界面)的缩写。

在GUI中,并不只是输入文本和返回文本,用户可以看到窗口、按钮、文本框等图形,

而且可以用鼠标单击,还可以通过键盘输入。

GUI是与程序交互不同的一种方式。GUI有三个基本要素:输入、处理和输出。 


工具包	描述
wxPython	python语言的一套GUI图形库,可以方便地创建完整的GUI用户界面
Kivy	开源工具包,能让相同源代码创建的程序跨平台运行
Flexx	纯python工具包,用来创建图形化界面应用程序。使用Web技术进行界面的渲染
PyQt	是Qt库的python版本,支持跨平台
Tkinter	是TK图形用户界面工具包标准的python接口。TK是一个轻量级的跨平台图形GUI开发工具
Pywin32	允许用户像VC一样使用python开发win32应用
PyGTK	让用户轻松创建具有图形用户界面的程序
pyui4win	开源的采用自绘技术的界面库 



pandas

requests

matplotlib

numpy

UserWarning: mkl-service package failed to import, therefore Intel(R) MKL initialization的问题,网上找了几个方法都没有解决。但是解决方案都和numpy和pytorch有关系,所以我尝试重新安装numpy,但是仍然出现问题。

解决方案:注意,因为我使用的anaconda,而 conda可以等价为pip。
(1)先删除numpy



D:\anaconda
D:\anaconda\Scripts
D:\anaconda\Library\bin
D:\anaconda\Library\mingw-w64\bin    
    
pip show Pillow


conda uninstall numpy 
(2)重新安装numpy

conda install numpy 
(3)删除mkl-service

matplotlib

conda uninstall mkl-service 
(4)重新安装mkl-service

conda install mkl-service 


conda install scikit-learn

Scikit-learn(以前称为scikits.learn,也称为sklearn)
是针对Python 编程语言的免费软件机器学习库。

它具有各种分类,回归和聚类算法,包括支持向量机,随机森林,梯度提升,k均值和DBSCAN,
并且旨在与Python数值科学库NumPy和SciPy联合使用。



直接将下面的代码复制到终端来添加清华和中科大的源(注意(1)是http不是https,否则会出现CondaHTTPError(2)越往后添加的源优先级越高,清华的源似乎很容易挂,建议按照我这个顺序添加)就可以加速了 ,之后conda install会快很多。(截止到20211030日都是有用的)

conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/pkgs/main/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/pkgs/free/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/cloud/msys2/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/cloud/bioconda/
conda config --add channels http://mirrors.ustc.edu.cn/anaconda/cloud/menpo/
conda config --set show_channel_urls yes


conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
 
//设置搜索时显示通道地址
conda config --set show_channel_urls yes


补充
想恢复默认可以使用以下指令删掉添加的源

conda config --remove-key channels
通过以下指令可以看到已经添加的源,在conda install的时候会根据优先级寻找包

conda config --get channels


清华镜像源
conda install加速镜像配置
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
———————————————— 

模块

bson

不依赖于MongoDB的独立的Python BSON编解码器。

certifi

提供了Mozilla精心管理的根证书集合,用于验证SSL证书的可信度,
同时验证TLS主机的身份。它是从要求项目。

要引用已安装的证书颁发机构(CA)包,您可以使用内置函数:

>>> import certifi

>>> certifi.where()
'/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'
或者从命令行:

$ python -m certifi
/usr/local/lib/python3.7/site-packages/certifi/cacert.pem

charset-normalizer

通用字符集检测器


通用字符集编码检测器

比它的对手Chardet更好的性能

Chardet在较大文件(1MB以上)上的性能很差。预计大有效载荷会有很大的不同。
硬币指示器 (coin-levelindicator的缩写)命令行界面(Command Line Interface for batch scripting)
这个软件包附带了一个CLI。

usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD]
                  file [file ...]

The Real First Universal Charset Detector. Discover originating encoding used
on text file. Normalize text to unicode.

positional arguments:
  files                 File(s) to be analysed

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         Display complementary information about file if any.
                        Stdout will contain logs about the detection process.
  -a, --with-alternative
                        Output complementary possibilities if any. Top-level
                        JSON WILL be a list.
  -n, --normalize       Permit to normalize input file. If not set, program
                        does not write anything.
  -m, --minimal         Only output the charset detected to STDOUT. Disabling
                        JSON output.
  -r, --replace         Replace file when trying to normalize it instead of
                        creating a new one.
  -f, --force           Replace file without asking if you are sure, use this
                        flag with caution.
  -t THRESHOLD, --threshold THRESHOLD
                        Define a custom maximum amount of chaos allowed in
                        decoded content. 0. <= chaos <= 1.
  --version             Show version information and exit.
  
  
  
  
  
  :tada:从版本1.4.0开始,CLI以JSON格式生成易于使用的stdout结果。

{
    "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt",
    "encoding": "cp1252",
    "encoding_aliases": [
        "1252",
        "windows_1252"
    ],
    "alternative_encodings": [
        "cp1254",
        "cp1256",
        "cp1258",
        "iso8859_14",
        "iso8859_15",
        "iso8859_16",
        "iso8859_3",
        "iso8859_9",
        "latin_1",
        "mbcs"
    ],
    "language": "French",
    "alphabets": [
        "Basic Latin",
        "Latin-1 Supplement"
    ],
    "has_sig_or_bom": false,
    "chaos": 0.149,
    "coherence": 97.152,
    "unicode_path": null,
    "is_preferred": true
}
只需打印出规范化的文本

from charset_normalizer import from_path

results = from_path('./my_subtitle.srt')

print(str(results.best()))
轻松升级您的代码

from charset_normalizer import detect

click

用于以可组合的方式用尽可能少的代码创建漂亮的命令行界面。它是“命令行界面创建工具包”。它是高度可配置的,但是有现成的合理的默认值。

它旨在使编写命令行工具的过程变得快速而有趣,同时也防止了由于无法实现预期的CLI API而导致的任何挫折。

单击三个点:

命令的任意嵌套

自动帮助页面生成

支持运行时子命令的延迟加载

colorama

可以让你的Terminal呈现出丰富多彩的颜色

输出一种跨平台的ANSI转义序列,
Terminal收到这种特殊的序列后并不直接显示ASCII字符,而是显示指定的颜色。

crontab

crontab python 不是内置库,而是一个第三方模块,

用于读写 crontab 文件和访问系统 cron。
您需要安装 python-crontab 而不是 crontab 来使用它。
您可以使用 crontab 的语法来安排 Python 脚本在特定的时间和日期执行

python -m pip install  python-crontab  -i "https://pypi.doubanio.com/simple/"

DBUtils

Python 编程中可以使用 PyMysql 进行数据库的连接及诸如查询/插入/更新等操作,
但是每次连接 MySQL 数据库请求时,都是独立的去请求访问,相当浪费资源,而且访问数量达到一定数量时,

对 mysql 的性能会产生较大的影响。


因此,实际使用中,通常会使用数据库的连接池技术,来访问数据库达到资源复用的目的。
DBUtils 是一套 Python 数据库连接池包,

并允许对非线程安全的数据库接口进行线程安全包装。DBUtils 来自 Webware for Python 。


套用于管理数据库连接池的Python包,
为高频度高并发的数据库访问提供更好的性能,
可以自动管理连接对象的创建和释放。并允许对非线程安全的数据库接口进行线程安全包装。



DButils:不仅仅支持pymysql

python -m pip install DBUtils -i "https://pypi.doubanio.com/simple/" 


使用DButils管理连接池,操作数据库,遇到的问题
PooledDB:配置连接池,提供共享数据库连接时,将连接和游标设置为类的实例变量,导致多线程执行,
获取到的共享的连接和游标,导致第一次查询之后,
会将设置为共享实例变量的pool_db和pool_cursor放回连接池,这时候再获取,就会报错

解决方法: 不共享连接和游标,直接返回连接和游标使用,可看下面的完整代码


 

DBUtils提供两种外部接口:

  

    PersistentDB :提供线程专用的数据库连接,并自动管理连接。
    PooledDB :提供线程间可共享的数据库连接,并自动管理连接。
    把连接放回连接池而不是真正的关闭
    需要库
    1、DBUtils pip install DBUtils
    2、pymysql pip install pymysql/MySQLdb
    
https://www.cnblogs.com/ztxd/articles/16944844.html

dnspython

Flask-WTF

提供了简单地 WTForms 的集成

http://www.pythondoc.com/flask-wtf/





功能
集成 wtforms。
带有 csrf 令牌的安全表单。
全局的 csrf 保护。
支持验证码(Recaptcha)。
与 Flask-Uploads 一起支持文件上传。
国际化集成。


我们可以实现数据的上传,获取,但是在数据提交的过程当中,
没有进行任何的数据校验,并且对提交者身份,位置都没有校验,这样的表单存在很大的风险。


WTF提交校验
web校验分为两种:

​ 前端校验: 在页面上,使用js对提交的数据进行校验,
由于可以通过浏览器的调试模式可以修改前端代码,而且可以不通过表单提交数据,所以有缺陷。

​ onsubmit = “return fun()”

​ 后端校验:在数据提交到服务器,进行处理之前,进行逻辑校验,这样的校验也会加重服务器的压力。

​ 后端校验如果纯手写会很复杂。 

PYCHARM的安装

PYTHON入门

变量练习题

字符串

分支语句

字符串分支语句练习题

列表

循环

元组

数组循环练习题

字典

函数

包和模块

类和对象

项目实战一 (爬虫方向)

基础

异步

import asyncio

async def submit_task_async(task_data):
    # do something with task_data
    return result

async def main():
    task_data_list = []
    for domain_target in domain_list:
        task_data = build_task_data(task_name=name, task_target=domain_target,
                                    task_type=TaskType.DOMAIN, task_tag=TaskTag.TASK,
                                    options=options)
        task_data_list.append(task_data)
    tasks = [asyncio.create_task(submit_task_async(task_data)) for task_data in task_data_list]
    results = await asyncio.gather(*tasks)
    # do something with results

asyncio.run(main())

文件

打开

写入模式 ‘w’

with open('temp/log.txt', 'w') as f:
        pass
打开一个名为 temp/log.txt 的文件,并以写入模式 'w' 打开它。

在 with 语句中使用 open() 函数打开文件后,将其赋值给变量 f。
通过这种方式打开文件,在 with 语句块结束时,文件会自动关闭,无需手动调用 f.close()

读取

txt文件

使用read()函数逐个字节或者字符读取txt文件中的内容

使用readline()函数逐行读取txt文件中的内容

使用readlines()函数一次性读取txt文件中多行内容

file 为打开的文件对象。
和 read()、readline() 函数一样,它要求打开文件的模式必须为可读模式(包括 r、rb、r+、rb+ 4 种)。
(unicode error) 'unicodeescape' codec can't decode bytes in position 18-19: truncated \uXXXX escape

在文件夹中复制地址时,文件夹中的地址是用 \ 来分隔不同文件夹的,而Python识别地址时只能识别用 / 分隔的地址。


在字符串前加上r或R
imread(r'C:\Users\li735\PycharmProjects\untitled\abc.txt') 

在“\”前加上”\”实现转义。


将“\”换为“/”


python字符串前缀的知识
1、在字符串前加上r或R表示该字符串是非转义的原始字符串。
2、在字符串前加上u或U表示该字符串是unicode字符串。

字符串前加 b
表示这是一个 bytes 对象
IndentationError: unexpected indent
缩进
python把word转换成pdf。
"D:\python3.7\Scripts\docx2pdf.exe"
使用docx2pdf python包,它可以作为命令行或python库来批量转换docx文件。


另一种是使用comtypes或win32com.client模块,它们可以利用Word应用程序的COM自动化来打开和保存文档


分别使用docx2pdf和comtypes模块来转换word文件为pdf文件。请注意,这些方法都需要安装Microsoft Office,并且可能只适用于Windows系统。

使用docx2pdf模块:

from docx2pdf import convert
word_file = r'src.docx'
pdf_file = 'study.pdf'
with open(pdf_file, "wb") as f:
    pass
docx2pdf.convert(word_file, pdf_file)
使用comtypes模块:

import sys
import os
import comtypes.client

wdFormatPDF = 17

in_file = os.path.abspath(sys.argv[1])
out_file = os.path.abspath(sys.argv[2])

word = comtypes.client.CreateObject('Word.Application')
doc = word.Documents.Open(in_file)
doc.SaveAs(out_file, FileFormat=wdFormatPDF)
doc.Close()
word.Quit()

按照字符长度去排版文本:

from docx import Document
from docx.shared import Inches

document = Document()

# 创建一个段落对象
paragraph = document.add_paragraph()

# 设置段落的左右缩进为1英寸
paragraph_format = paragraph.paragraph_format
paragraph_format.left_indent = Inches(1)
paragraph_format.right_indent = Inches(1)

# 添加一个文本对象,并设置其字体大小为20磅
run = paragraph.add_run("这是一个测试文本,它的长度是20个字符。")
run.font.size = 200000 # 20磅等于200000英分

# 保存文档
document.save("test.docx")
这个代码会创建一个docx文件,其中包含一个段落,该段落的左右缩进为1英寸,文本对象的字体大小为20磅。12

如果您想按照字符数来设置缩进,您可以使用以下公式:

indent_in_inches = character_count * character_width_in_inches / 100.0
其中 character_count 是您想要缩进的字符数,character_width_in_inches 是每个字符在指定字体和大小下的平均宽度(单位为英寸)。3

例如,如果您想要将段落的第一行缩进5个字符,假设每个字符的平均宽度为0.08英寸,则可以使用以下代码:

from docx import Document
from docx.shared import Inches

document = Document()

# 创建一个段落对象
paragraph = document.add_paragraph()

# 设置段落的第一行缩进为5个字符的宽度(约0.4英寸)
paragraph_format = paragraph.paragraph_format
paragraph_format.first_line_indent = Inches(5 * 0.08 / 100.0)

# 添加一个文本对象,并设置其字体大小为20磅
run = paragraph.add_run("这是一个测试文本,它的长度是20个字符。")
run.font.size = 200000 # 20磅等于200000英分

# 保存文档
document.save("test.docx")




时间

now.strftime(%Y-%m-%d %H:%M:%S’) 
是一个Python语句,用于将now变量中的日期和时间对象转换为字符串格式12。
now变量通常是使用datetime模块中的datetime类创建的,
例如:from datetime import datetime; now = datetime.now() 1。

strftime()方法接受一个或多个格式代码作为参数,并根据它们返回一个格式化的字符串。格式代码表示日期和时间的不同部分,例如年、月、日、时、分、秒等12。

‘%Y-%m-%d %H:%M:%S’ 是一个格式字符串,其中%Y表示四位数的年份,%m表示两位数的月份,%d表示两位数的日期,%H表示24小时制的小时,%M表示两位数的分钟,%S表示两位数的秒钟32。
        
        
例如,如果now变量中存储的日期和时间是2021121600:50:27,则执行now.strftime(%Y-%m-%d %H:%M:%S’) 会返回’2021-12-16 00:50:27’ 这样一个字符串。
                
                
                
                
                
                
您可以使用datetime模块中的date和today方法,将时间转换为日期,并与今天的日期进行比较1from datetime import datetime
time_str = "2023-02-15 20:38:15" # 给定的时间字符串
time_obj = datetime.strptime (time_str, "%Y-%m-%d %H:%M:%S") # 将字符串转换为datetime对象
time_date = time_obj.date () # 获取datetime对象的日期部分
today_date = datetime.today ().date () # 获取今天的日期
if time_date == today_date: # 比较两个日期是否相等
  print ("The given time is today")
else:
  print ("The given time is not today")
您也可以使用calendar模块中的day_name和weekday方法,获取给定时间和今天的星期几,并进行比较2from datetime import datetime
import calendar
time_str = "2023-02-15 20:38:15" # 给定的时间字符串
time_obj = datetime.strptime (time_str, "%Y-%m-%d %H:%M:%S") # 将字符串转换为datetime对象
time_day = calendar.day_name [time_obj.weekday ()] # 获取datetime对象的星期几(英文)
today_day = calendar.day_name [datetime.today ().weekday ()] # 获取今天的星期几(英文)
if time_day == today_day: # 比较两个星期几是否相同
  print ("The given time is today")
else:
  print ("The given time is not today")





您可以使用datetime模块中的date和timedelta类,将今天的日期减去一天得到昨天的日期12from datetime import date, timedelta
today = date.today () # 获取今天的日期
yesterday = today - timedelta (days=1) # 获取昨天的日期
print (yesterday) # 打印昨天的日期,格式为YYYY-MM-DD
您也可以使用datetime模块中的datetime和timedelta类,将当前时间减去一天得到昨天的时间,并用strftime方法将其格式化为只包含日期部分3from datetime import datetime, timedelta
now = datetime.now () # 获取当前时间
yesterday = now - timedelta (days=1) # 获取昨天的时间
yesterday_date = yesterday.strftime ("%Y-%m-%d") # 将昨天的时间格式化为只包含日期部分
print (yesterday_date) # 打印昨天的日期,格式为YYYY-MM-DD












判断一个类似于2023-02-15 20:38:15的时间是否是本周内的日期,有几种可能的方法。例如:

您可以使用datetime模块中的isocalendar方法,将时间转换为ISO格式的年份、周数和星期几,并与当前时间进行比较1from datetime import datetime
time_str = "2023-02-15 20:38:15" # 给定的时间字符串
time_obj = datetime.strptime (time_str, "%Y-%m-%d %H:%M:%S") # 将字符串转换为datetime对象
time_year, time_week, time_day = time_obj.isocalendar () # 获取datetime对象的ISO格式的年份、周数和星期几
now_year, now_week, now_day = datetime.now ().isocalendar () # 获取当前时间的ISO格式的年份、周数和星期几
if time_year == now_year and time_week == now_week: # 比较两个时间是否在同一年同一周内
  print ("The given time is in the current week")
else:
  print ("The given time is not in the current week")
您也可以使用calendar模块中的monthcalendar方法,获取给定时间所在月份的日历,并检查给定时间是否在当前日期所在行2from datetime import datetime
import calendar
time_str = "2023-02-15 20:38:15" # 给定的时间字符串
time_obj = datetime.strptime (time_str, "%Y-%m-%d %H:%M:%S") # 将字符串转换为datetime对象
cal = calendar.monthcalendar (time_obj.year, time_obj.month) # 获取datetime对象所在月份的日历,返回一个二维列表,每个子列表表示一周,每个元素表示一天(0表示空白)
now_obj = datetime.now () # 获取当前时间
for week in cal: # 遍历日历中每一周
  if now_obj.day in week and time_obj.day in week: # 如果当前日期和给定日期都在同一周内(即同一个子列表中)
    print ("The given time is in the current week")
    break # 跳出循环
else: # 如果没有找到匹配项,则执行else语句(注意这里else与for对齐)
  print ("The given time is not in the current week")

魔术方法

类型注解

  __file__  py文件的位置
  
  
  Python 所有魔术方法的笔记是指用 Python 编写的一些关于魔术方法的学习或总结的文档,魔术方法是指一些以双下划线开头和结尾的特殊方法,它们可以被 Python 解释器隐式地调用来执行对应的操作123。例如:

# 定义一个类
class Point:
    # 构造方法
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # 字符串表示方法
    def __str__(self):
        return f"Point({
     self.x}, {
     self.y})"
    
    # 加法运算符重载方法
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

# 创建两个对象
p1 = Point(1, 2)
p2 = Point(3, 4)

# 打印对象
print(p1) # 调用 __str__ 方法
print(p2) # 调用 __str__ 方法

# 计算对象之和
p3 = p1 + p2 # 调用 __add__ 方法

# 打印对象之和
print(p3) # 调用 __str__ 方法
这个 Python 代码包含了一个类 Point,它有三个魔术方法:init, str 和 add。其中,init 方法是构造方法,它在创建对象时被调用;str 方法是字符串表示方法,它在打印对象时被调用;add 方法是加法运算符重载方法,它在计算对象之和时被调用。这样的代码可以实现自定义类的初始化、显示和运算1。


魔术方法可以用来定义预定义运算符的重载行为,或者自定义一些常见的操作或结构123。例如:

# 定义一个类
class Vector:
    # 构造方法
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # 字符串表示方法
    def __str__(self):
        return f"Vector({
     self.x}, {
     self.y})"
    
    # 加法运算符重载方法
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    # 减法运算符重载方法
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    
    # 乘法运算符重载方法
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    # 反向乘法运算符重载方法
    def __rmul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    # 取反运算符重载方法
    def __neg__(self):
        return Vector(-self.x, -self.y)

# 创建两个对象
v1 = Vector(1, 2)
v2 = Vector(3, 4)

# 计算对象之和、差、积和反向积
v3 = v1 + v2 # 调用 __add__ 方法
v4 = v1 - v2 # 调用 __sub__ 方法
v5 = v1 * 2  # 调用 __mul__ 方法
v6 = 2 * v1  # 调用 __rmul__ 方法

# 打印对象之和、差、积和反向积
print(v3) # 调用 __str__ 方法,输出 Vector(4, 6)
print(v4) # 调用 __str__ 方法,输出 Vector(-2, -2)
print(v5) # 调用 __str__ 方法,输出 Vector(2, 4)
print(v6) # 调用 __str__ 方法,输出 Vector(2, 4)

# 取反对象并打印结果
v7 = -v1   # 调用 __neg__ 方法 
print(v7) # 调用 __str__ 方法,输出 Vector(-1,-2)
这个 Python 代码包含了一个类 Vector,它有七个魔术方法:init, str, add, sub, mul, rmul 和 neg。其中,除了前两个已经介绍过的魔术方法外,其他五个都是对应不同的运算符:加法(+), 减法(-), 乘法(), 反向乘法(), 取反(-)。这样的代码可以实现自定义类的各种数学运算






print(dir())

['__annotations__', '__builtins__', '__cached__', '__doc__', 
'__file__', '__loader__', '__name__', '__package__', '__spec__']

__annotations__:预定义的变量类型
__doc__:文档注释,仅包括第一个''' '''内部的注释文档
__file__:文件名,根据被引用还是被执行返回绝对路径还是相对路径
__name_:文件名,被执行文件该属性为__main__,被引用文件则返回包名
-> 表示函数的返回值类型。这是 Python 3.5 引入的类型注解功能的一部分

进程

监控另一个 Python 脚本是否正在运行。一种方法是使用 psutil 库来检查系统中正在运行的进程。下面是一个示例代码,它定义了一个名为 is_running 的函数,该函数接受脚本名称作为参数,并返回一个布尔值,指示该脚本是否正在运行:

import psutil

def is_running(script):
    for process in psutil.process_iter():
        if process.name().startswith('python'):
            if len(process.cmdline()) > 1 and script in process.cmdline()[1]:
                return True
    return False
在上面的代码中,我们遍历系统中的所有进程,并检查进程名称是否以 'python' 开头。如果是,则检查进程的命令行参数中是否包含给定的脚本名称。如果找到匹配,则返回 True;否则,返回 False

函数


用面向对象编程的例子1class MyClass (object):
  def __init__ (self):
    self.a = ['A','X','R','N','L'] # 共享的实例成员
  def fun1 (self, string):
    out = []
    for letter in self.a:
      out.append (string+letter)
    return out
  def fun2 (self, number):
    out = []
    for letter in self.a:
      out.append (str (number)+letter)
    return out
a = MyClass ()
x = a.fun1 ('Hello ')
y = a.fun2 (2)
利用Python的作用域规则的例子1:
a = ['A','X','R','N','L']
def fun1(string):
  out = []
  for letter in a:
    out.append(string+letter)
  return out
def fun2(number):
  out = []
  for letter in a:
    out.append(str(number)+letter)
  return out
x = fun1('Hello ')
y = fun2(2)
使用Redis等工具的例子2# script_one.py
from redis import Redis
from time import sleep

cli = Redis('localhost')
shared_var = 1

while True:
  cli.set('share_place', shared_var)
  shared_var += 1
  sleep(1)

# script_two.py
from redis import Redis

cli = Redis('localhost')

while True:
  print(cli.get('share_place'))

















def add_one (x): # x是一个参数
  return x + 1 # 返回x加1的结果

y = 5 # 定义一个变量y
z = add_one (y) # 调用函数并传递y作为参数
print (z) # 打印函数的返回值,即6
将变量定义为全局变量,并在函数中使用global关键字声明它的例子2:
x = 5 # 定义一个全局变量x

def change_x (): # 定义一个函数
  global x # 声明要使用全局变量x
  x = 10 # 修改全局变量x的值

print (x) # 打印全局变量x的值,即5
change_x () # 调用函数并修改全局变量x的值
print (x) # 打印全局变量x的值,即10
将变量存储在一个文件中,并使用open和read/write等函数来读取或写入它的例子3# 写入文件example.txt
f = open ("example.txt", "w") # 打开一个文件,如果不存在则创建它,模式为写入(w)
f.write ("Hello world\n") # 写入一行内容到文件中
f.write ("This is an example\n") # 写入另一行内容到文件中
f.close () # 关闭文件

# 读取文件example.txt
f = open ("example.txt", "r") # 打开一个文件,模式为读取(r)
content = f.read () # 读取文件的全部内容到一个字符串中
print (content) # 打印字符串内容,即两行文本
f.close () # 关闭文件

# 追加内容到文件example.txt
f = open ("example.txt", "a") # 打开一个文件,模式为追加(a)
f.write ("This is another line\n") # 追加一行内容到文件末尾
f.close () # 关闭文件

# 再次读取文件example.txt并打印内容,此时有三行文本。

    带有“__init__.py”文件的目录
 被认为是Python的包目录  与目录的图标有不一样的显示


Python 定义了两种类型的包,常规包和命名空间包。


常规包是传统的包,因为它们存在于 Python 3.2 和更早的版本中。

一个常规包通常被实现为一个包含__init__.py 文件的目录。

当一个常规包被导入时,这个__init__.py文件被隐式执行,
它所定义的对象被绑定到包的名字空间中。

Python文件都是按照目录当作不同的模块来组织的,这个目录被认为是Python包目录,
Python会通过搜索该目录下的文件来导入相关的模块。

但是并不是所有的目录都会被搜索添加,
只有当目录中包含__init__.py文件时,这个目录才会被Python当作是一个包目录,

进而搜索添加里面的文件。  可以使用import xx.xx的方式导入目录下的文件或者模块。

这样做可以让编程者自己控制哪些目录可以被Python导入成包。

当某个目录中包含__init__.py文件时,
Python在引入这个模块之前,会首先执行这个文件。

因此,这个文件也可以被编程者用来控制
定义包级别的变量。
如果你要import的文件和你要测试的文件在同一个目录下,你可以直接使用import 文件名,不需要加.py后缀。例如,如果你要测试的文件是test.py,你要import的文件是func.py,你可以在test.py中写import func,然后调用func中的函数。
如果你要import的文件在你要测试的文件的子目录下,你可以使用点号(.)来分隔目录和文件名。例如,如果你要测试的文件是test.py,你要import的文件是subdir/func.py,你可以在test.py中写import subdir.func,然后调用func中的函数。这个方法需要Python 3.3或更高版本。
如果你要import的文件在你要测试的文件的不同目录下,你可以使用sys模块来修改Python搜索路径。例如,如果你要测试的文件是test.py,你要import的文件是app/folder/func.py,你可以在test.py中写import sys; sys.path.insert(1, '/path/to/application/app/folder'); import func,然后调用func中的函数。注意这个方法可能会导致命名冲突或不可预期的结果。

数据类型 String 字符串

字面量






[Python 中,r’ b’ 等开头的字符串是字符串字面量的前缀,表示字符串的不同类型](https://stackoverflow.com/questions/41155382/add-r-prefix-to-a-python-variable)[1](https://stackoverflow.com/questions/41155382/add-r-prefix-to-a-python-variable)[2](https://stackoverflow.com/questions/4780088/what-does-preceding-a-string-literal-with-r-mean):

-   [**r** 表示原始字符串,即不会对反斜杠(\)进行转义,而是将其作为普通字符](https://stackoverflow.com/questions/41155382/add-r-prefix-to-a-python-variable)[1](https://stackoverflow.com/questions/41155382/add-r-prefix-to-a-python-variable)[2](https://stackoverflow.com/questions/4780088/what-does-preceding-a-string-literal-with-r-mean)。例如,r’\n’ 是一个包含反斜杠和字母 n 的字符串,而 ‘\n’ 是一个换行符。
-   [**b** 表示字节字符串,即由字节组成的不可变序列](https://stackoverflow.com/questions/2592764/what-does-a-b-prefix-before-a-python-string-mean)[3](https://stackoverflow.com/questions/2592764/what-does-a-b-prefix-before-a-python-string-mean)[。在 Python 3 中,字符串默认是 Unicode 类型,如果要表示字节类型,需要使用 b 前缀](https://stackoverflow.com/questions/2592764/what-does-a-b-prefix-before-a-python-string-mean)[3](https://stackoverflow.com/questions/2592764/what-does-a-b-prefix-before-a-python-string-mean)。例如,b’hello’ 是一个包含五个字节的对象,而 ‘hello’ 是一个包含五个 Unicode 字符的对象。
-   [**u** 表示 Unicode 字符串,即由 Unicode 字符组成的不可变序列](https://docs.python.org/3/library/re.html)[4](https://docs.python.org/3/library/re.html)[。在 Python 2 中,字符串默认是字节类型,如果要表示 Unicode 类型,需要使用 u 前缀](https://docs.python.org/3/library/re.html)[4](https://docs.python.org/3/library/re.html)。例如,u’你好’ 是一个包含两个 Unicode 字符的对象,而 ‘你好’ 是一个包含六个字节的对象。

字符去除

s = "21-2"
# 方法一(通用)
# 找到‘-’的索引值,然后加一取出减号后面的值
index = s.find('-')+1
print(s[index:])
# 方法二(手工计算便宜)
# 数偏移量
print(s[3:])
# 方法三(取巧,利用-分隔)
# 已‘-’为分隔符,取后面的内容
print(s.split('-')[1])

逆序数字

逆序输出数字:

方法一:

numbers = [1, 2, 3, 4, 5]

for i in range(len(numbers)-1, -1, -1):

print(numbers[i])

这段代码使用了 range 函数,它的三个参数分别是:起始位置,终止位置,步长。终止位置是 -1 表示到列表末尾,步长是 -1 表示每次倒序推进一个位置。

方法二:

n = int(input("请输入一个数字:")) #将数字转换为字符串

s = str(n) #倒序输出字符串

print(s[::-1])

方法三:

n = int(input("请输入一个数字:")) #初始化变量

rev = 0 #不断取余取整,将余数加入变量rev中

while n > 0:

rev = rev * 10 + n % 10

n = n / 10

print(int(rev))

方法四:

n = int(input('请输入一个数字:'))

while n>0:

print(n) n = n - 1

方法五:

n = int(input('请输入一个数字:'))

for i in range(n, 0, -1):

print(i)

PS:Python range函数用法:

range(start, stop[, step])

参数说明:

start:计数从start开始。默认是从0开始。例如range5)等价于range05;

stop:计数到stop结束,但不包括stop。例如:range05) 是[0, 1, 2, 3, 4]没有5 即:range(start, stop);

step:步长,默认为1。例如:range052)就是[0, 2, 4]

注意事项:

1. start,stop,step都可以是负数,例如:range(5,-5,-2)

2. start,stop都可以是浮点数或字符串,但step只能是整数,例如:range(0.0, 5.0, 2)

3. 如果step为0,则会报错。

4. 如果start大于stop,则会返回一个空列表,例如:range(5, 0, 1)

格式化

     
                %C 格式化字符及其ASCII码

%s 格式化字符串

%d 格式化整数

%u 格式化无符号整型

%o 格式化无符号八进制数

%X 格式化无符号十六进制数

%X 格式化无符号十六进制数(大写)

%f 格式化浮点数字,可指定小数点后的精度

%e 用科学计数法格式化浮点数

%E 作用同%e,用科学计数法格式化浮点数

%g %f和%e的简写

%G %F和%E的简写

%p 用十六进制数格式化变量的地址  

切片

使用replace()方法的第三个参数max,指定替换次数为1。例如:
s = "hello:world"
s = s.replace(":", "", 1) # 只替换第一个冒号为空字符
print(s) # 输出 helloworld
使用split()方法按冒号分割字符串,然后取第二个元素。例如:
s = "hello:world"
s = s.split(":")[1] # 按冒号分割字符串,取第二个元素
print(s) # 输出 world
使用切片操作符[slice]按索引截取字符串,找到第一个冒号的位置,然后从它后面开始截取。例如:
s = "hello:world"
i = s.find(":") # 找到第一个冒号的位置
s = s[i+1:] # 从它后面开始截取字符串
print(s) # 输出 world

去空格

  1:strip()方法,去除字符串开头或者结尾的空格

>>> a = " a b c "
>>> a.strip()
'a b c'
    2:lstrip()方法,去除字符串开头的空格

>>> a = " a b c "
>>> a.lstrip()
'a b c '
    3:rstrip()方法,去除字符串结尾的空格

>>> a = " a b c "
>>> a.rstrip()
' a b c'
    4:replace()方法,可以去除全部空格

# replace主要用于字符串的替换replace(old, new, count)
>>> a = " a b c "
>>> a.replace(" ", "")
'abc'
    5: join()方法 split()方法,可以去除全部空格

# join为字符字符串合成传入一个字符串列表,split用于字符串分割可以按规则进行分割
>>> a = " a b c "
>>> b = a.split()  # 字符串按空格分割成列表
>>> b ['a', 'b', 'c']
>>> c = "".join(b) # 使用一个空字符串合成列表内容生成新的字符串
>>> c 'abc'
 
# 快捷用法
>>> a = " a b c "
>>> "".join(a.split())
'abc'

参数类型

编写一个函数,将函数的参数类型打印出来:

def print_arg_types(*args):
    for arg in args:
        print(type(arg))

print_arg_types(1, "hello", True) # 输出 <class 'int'> <class 'str'> <class 'bool'>
这个函数使用了 *args 参数,可以接受任意数量的位置参数,并用 type() 函数获取它们的类型。12

如果您想打印关键字参数的类型,您可以使用 **kwargs 参数,并用 items() 方法遍历它们。例如:

def print_kwarg_types(**kwargs):
    for key, value in kwargs.items():
        print(key, type(value))

print_kwarg_types(name="Alice", age=20) # 输出 name <class 'str'> age <class 'int'>

字符

Python中字符串前“b”,“r”,“u”,“f”的作用
1、字符串前加 u

例:u"我是含有中文字符组成的字符串。"

作用:

前缀u表示该字符串是unicode编码,Python2中用,用在含有中文字符的字符串前,防止因为编码问题,导致中文出现乱码。另外一般要在文件开关标明编码方式采用utf8。

Python3中,所有字符串默认都是unicode字符串。

2、字符串前加 r

例:r"\n\n\n\n”  表示一个普通字符串 \n\n\n\n,而不表示换行了。

作用:

去掉反斜杠的转义机制。

在普通字符串中,反斜线是转义符,代表一些特殊的内容,如换行符\n。前缀r表示该字符串是原始字符串,即\不是转义符,只是单纯的一个符号。

常用于特殊的字符如换行符、正则表达式、文件路径。

注意不能在原始字符串结尾输入反斜线,否则Python不知道这是一个字符还是换行符(字符串最后用\表示换行),会报错:

>>> print(r'C:\Program File\my\path''\')  
  File "<stdin>", line 1
    print(r'C:\Program File\my\path''\')
                                        ^
SyntaxError: EOL while scanning string literal
1
2
3
4
5
那如果是一个文件夹路径就是以\结尾怎么办呢,可以再接一个转义\的字符串:

>>> print(r'C:\Program File\my\path''\\')
C:\Program File\my\path\
1
2
或、

>>> print(r'C:\Program File\my\path'+'\\') 
C:\Program File\my\path\
1
2
注意:
在python的正则表达式中,为表示模块re要求的单个反斜杠,需要在字符串中书写两个反斜杠,让解释器对其进行转义。换而言之,这里包含两层转义:解释器执行的转义和模块re执行的转义。实际上,在有些情况下也可使用单个反斜杠,让解释器自动对其进行转义,但请不要这样依赖解释器。
如果你厌烦了两个反斜杆,可使用原始字符串,如r'python\.org'3、字符串前加 b

例:response = b'Hello World!'

b' ' 表示这是一个 bytes 对象,
用在Python3中,
默认的strunicode类。Python2的str本身就是bytes类。

          
作用:

b" "前缀表示:后面字符串是bytes 类型。

用处:

前缀b表示该字符串是bytes类型。

常用在如网络编程中,
服务器和浏览器只认bytes类型数据。
如:send 函数的参数和 recv 函数的返回值都是 bytes 类型。
          
Python 中的一种数据类型,用于表示二进制数据。
          它可以存储任意字节的数据,包括文本、图像、音频等等。
          bytes 对象是不可变的,也就是说,一旦创建了一个 bytes 对象,就不能修改它的内容。
          bytes 只负责以字节序列的形式(二进制形式)来存储数据,
          至于这些数据到底表示什么内容(字符串、数字、图片、音频等),
          完全由程序的解析方式决定。

附:
在 Python3 中,bytesstr 的互相转换方式是

str.encode('utf-8')
bytes.decode('utf-8')
1
2
4、字符串前加 f

import time
t0 = time.time()
time.sleep(1)
name ='processing'
print(f'{
     name} done in {
     time.time() - t0:.2f} s')
1
2
3
4
5
输出:

processing done in 1.00 s
1
Python3.6新加特性,前缀f用来格式化字符串。可以看出f前缀可以更方便的格式化字符串,format()方法可读性高且使用方便。

而且加上f前缀后,支持在大括号内,运行Python表达式。

你还可以用fr前缀来表示原生字符串。

Python中bytes与字符串的相互转化
# bytes转字符串方式一
b=b'\xe9\x80\x86\xe7\x81\xab'
string=str(b,'utf-8')
print(string)
>>> 逆火
>>>
# bytes转字符串方式二
b=b'\xe9\x80\x86\xe7\x81\xab'
string=b.decode() # 第一参数默认utf8,第二参数默认strict
print(string)
>>> 逆火

# bytes转字符串方式三
b=b'\xe9\x80\x86\xe7\x81haha\xab'
string=b.decode('utf-8','ignore') # 忽略非法字符,用strict会抛出异常
print(string)
>>> 逆haha

# bytes转字符串方式四
b=b'\xe9\x80\x86\xe7\x81haha\xab'
string=b.decode('utf-8','replace') # 用?取代非法字符
print(string)
>>> 逆�haha�
>>>
# 字符串转bytes方式一
str1='逆火'
b=bytes(str1, encoding='utf-8')
print(b)
>>> b'\xe9\x80\x86\xe7\x81\xab'

# 字符串转bytes方式二
b=str1.encode('utf-8')
print(b)
>>> b'\xe9\x80\x86\xe7\x81\xab'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
前缀u、b测试
下面的内容来源于:https://blog.csdn.net/anlian523/article/details/80504699,原文有错误,特转过来修改

字符串的类型只有两种(strbytes),

>>> oath = '我爱妞'
>>> print(type(oath))
<class 'str'>
>>> print(len(oath))
3
1
2
3
4
5
>>> oath1 = u'我爱妞'
>>> print(type(oath1))
<class 'str'>
>>> print(len(oath1))
3
>>> print(oath==oath1)
True
1
2
3
4
5
6
7
发现无前缀,和前缀u,构造出来的字符串常量是一样的。

类型都是str,长度都是3==判断返回true。
其实,这里是因为,python3中,字符串的存储方式都是以Unicode字符来存储的,所以前缀带不带u,其实都一样。

>>> oath = '我爱妞'
>>> oath1 = u'我爱妞'
>>> print(oath is oath1)
False
1
2
3
4
is判断返回False。

结论:字符串常量,前缀带不带u,都是一样的。

>>> utf8 = oath.encode('utf-8')
>>> print(type(utf8))
<class 'bytes'>
>>> print(len(utf8))
9
>>> print(utf8)
b'\xe6\x88\x91\xe7\x88\xb1\xe5\xa6\x9e'
1
2
3
4
5
6
7
>>> gbk = oath.encode('gbk')
>>> print(type(gbk))
<class 'bytes'>
>>> print(len(gbk))
6
>>> print(gbk)
b'\xce\xd2\xb0\xae\xe6\xa4'
1
2
3
4
5
6
7
可以发现任何str类型的字符串,在经过encode(‘utf-8)后,通过utf-8编码,将Unicode字符转换为对应的以字节方式存储的若干十六进制数。

根据如上程序以及结果,可以发现,utf-8用三个字节(6个十六进制数)来表示一个中文字符,而gbk用两个字节(4个十六进制数)来表示一个中文字符。

结论:encode()函数根据括号内的编码方式,把str类型的字符串转换为bytes字符串,字符对应的若干十六进制数。

既然str存储的是Unicode字符,那么也可以Unicode编码来存储str,形如\u1234:

>>> u'\u5220\u9664'
'删除'
>>> '\u5220\u9664'
'删除'
1
2
3
4
发现\u后面跟四个十六进制数,就可以代表一个Unicode字符,同样的,前缀带不带u都一样。

>>> test = u'\u5220\u9664'
>>> print(len(test))
2
>>> print(test)
删除
>>> test1 = test.encode('utf-8')
>>> print(test1)
b'\xe5\x88\xa0\xe9\x99\xa4'
>>> print(type(test1))
<class 'bytes'>
1
2
3
4
5
6
7
8
9
10
结论:str类型的字符串,每个字符用字符本身或者\u1234来表示都可以,后者则是直接是Unicode编码。但打印时都是字符本身。

bytes字符串的组成形式,必须是十六进制数,或者ASCII字符:

>>> x = b'abc'
>>> x
b'abc'
>>> b'好'
  File "<stdin>", line 1
    b'好'
        ^
SyntaxError: bytes can only contain ASCII literal characters.
1
2
3
4
5
6
7
8
提示错误:bytes只能包含ASCII字符。

还可以对bytes取索引,所以bytes类型也可以用for循环来迭代。取索引,将所在元素的数,转换为十进制数。

>>> g=b'\xce\xd2\xb0\xae\xe6\xa4'
>>> g[0]
206
1
2
3
>>> out = open('test.txt','w',encoding = 'utf-8')
>>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

amingMM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值