python-第三方库-[yarl、yaml、yapf]

一: yarl

1> yarl 介绍

URL介绍:统一资源定位符,它是用来表示互联网上的某个资源地址,互联网上的每个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它;
yarl :yarl 库是一个强大的工具,用于处理 URL(统一资源定位符);
yarl作用:提供了简单且灵活的 API,使得 URL 的解析、构建和操作变得简单;

2> yarl.URL 介绍

from yarl import URL

1. yarl.URL 的语法格式

在这里插入图片描述

URL 的语法格式:
protocol://hostname[:port]/path[?query][#fragment]

part含义注释
protocol指网络传输协议以下是经常用到的几个协议;
http,通过 HTTP 协议访问该资源,格式 http://;
https,通过安全的 HTTPS 协议访问该资源, 格式 https://;
file,资源是本地计算机上的文件,格式 file://
ftp,通过 FTP访问资源,格式 FTP://
hostname主机名指存放资源的服务器的域名、主机名或 IP 地址。有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password@hostname)
port端口号port 是一个可选的整数,它的取值范围 是 0-65535。如果 port 被省略时就使用默认端口,各种传输协议都有默认的端口号,如 http 的默认端口为 80,https 的端口是 443;
path路由地址由零个或多个/符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。路由地址决定了服务端如何处理这个请求;
query查询从?开始到#为止,它们之间的部分就是参数,又称搜索部分或者查询字符串。这个部分允许有多个参数,参数与参数之间用&作为分隔符;下面demo 为:spm=1011.2124.3001.5298
fragment信息片断它用于指定网络资源中的片断,例如一个网页中有多个名词解释,那么可使用 fragment 直接对它们定位

2. yarl.URL demo

from yarl import URL

url_string = "https://mp.csdn.net/mp_blog/manage/article?spm=1011.2124.3001.5298"
url = URL(url_string)

print(url)
print(url.scheme)
print(url.host)
print(url.port)
print(url.authority)

print(url.path)
print(url.query)
print(url.query_string)

print(url.user)
print(url.password)
=======================
https://mp.csdn.net/mp_blog/manage/article?spm=1011.2124.3001.5298
https
mp.csdn.net
443
mp.csdn.net:443
/mp_blog/manage/article
<MultiDictProxy('spm': '1011.2124.3001.5298')>
spm=1011.2124.3001.5298

None
None

3. yarl.URL.build()

from yarl import URL

url = URL.build(
          scheme='https',
          host='mp.csdn.net',
          port=443,
          path='/mp_blog/manage/article',
          query={'spm': '1011.2124.3001.5298'}
          )
print(url)
===============
https://mp.csdn.net:443/mp_blog/manage/article?spm=1011.2124.3001.5298

4. yarl.URL().with_*()

with_scheme、with_user 、with_password 、with_host 、with_port、with_path、with_query、with_fragment、with_name

with_*() 单步骤构建

from yarl import URL

url = URL.build(
          scheme='https',
          host='mp.csdn.net',
          port=443,
          path='/mp_blog/manage/article',
          )
query = {'spm': '1011.2124.3001.5298'}

print(url.with_query(query))

with_().with_()多步骤构建url

from yarl import URL

url = URL.build(
          scheme='https',
          host='mp.csdn.net',
          port=443,
          )
print(url)
query = {'spm': '1011.2124.3001.5298'}
print(url.with_path('/mp_blog/manage/article').with_query(query))
============================
https://mp.csdn.net:443
https://mp.csdn.net:443/mp_blog/manage/article?spm=1011.2124.3001.5298

5. yarl.URL().update_query()

url.with_query(query):清除之前的query 信息;

from yarl import URL

url = URL.build(
          scheme='https',
          host='mp.csdn.net',
          port=443,
          path='/mp_blog/manage/article',
          query = {'spm': '1011.2124.3001.5298'}
          )

query = {'xxx': '127.0.0.1', '***': '128.0.0.1'}
print(url.with_query(query))
===================
https://mp.csdn.net:443/mp_blog/manage/article?xxx=127.0.0.1&***=128.0.0.1

url.update_query(query):对之前存在信息进行更新;

from yarl import URL

url = URL.build(
          scheme='https',
          host='mp.csdn.net',
          port=443,
          path='/mp_blog/manage/article',
          query = {'spm': '1011.2124.3001.5298'}
          )

query = {'xxx': '127.0.0.1', '***': '128.0.0.1'}
print(url.update_query(query))
=============================
https://mp.csdn.net:443/mp_blog/manage/article?spm=1011.2124.3001.5298&xxx=127.0.0.1&***=128.0.0.1

6> url / &%组合

from yarl import URL
url = (
URL('https://mp.csdn.net')/
'mp_blog/manage/article'%
{'spm': '1011.2124.3001.5298'}
)

print(url)
=====================
https://mp.csdn.net/mp_blog/manage/article?spm=1011.2124.3001.5298

二:yaml

1> yaml 介绍

Yaml :Yaml 是一种人类可读的数据序列化语言,通常用于存储项目中的配置文件;例如 docker 和 k8s 都使用 Yaml 文件定义部署信息;类似于 json 数据,但 Yaml 的格式更加丰富,可以存储更复杂的数据结构

2> yaml 基本规则

规则说明
层级关系yaml 的层级关系通过缩进表示,缩进空格数没有规定,但同层级的缩进必须一致。建议全局使用相同的缩进空格数;
存储数据yaml 使用键值对的方式存储数据。 - 在键值对的值前面添加 - 符号表示这个键的值是一个列表

1. 数据结构介绍

YAML中,有3种基本的数据结构:Scalars(标量)、Sequences(序列)和Mappings(映射)

数据结构说明举例
Scalars标量是单个的、不可再分的值。标量可以是字符串、数字、布尔值、null、日期等1. 普通样式、单/双引号样式
2. 字面样式(literal )
3. 折叠样式(folded)
序列(Sequences)序列是一组按次序排列的值,每一个元素都可以是任意数据类型连字符-开头的行构成一个序列;
- A
- B
- C
==>
key: [A, B, C]
Mappings(映射)映射是一种键值对的集合,其中每个键都必须唯一每个键值对用冒号+一个空格分隔(key: value)
普通样式、单/双引号样式
import yaml

document = """
爱好1: 喝酒
      唱歌
爱好2: '喝酒

      唱歌'
"""

res = yaml.load(document, Loader=yaml.Loader)
print(res)
============
{'爱好1': '喝酒 唱歌', '爱好2': '喝酒\n唱歌'}
字面样式(literal )
import yaml

document = """
爱好1: |
      喝酒
      唱歌
爱好2: '喝酒

      唱歌'
"""

res = yaml.load(document, Loader=yaml.Loader)
print(res)
=====================
{'爱好1': '喝酒\n唱歌\n', '爱好2': '喝酒\n唱歌'}
折叠样式(folded)
import yaml

document = """
爱好1: >
      喝酒
      唱歌
爱好2: '喝酒

      唱歌'
"""

res = yaml.load(document, Loader=yaml.Loader)
print(res)
==============
{'爱好1': '喝酒 唱歌\n', '爱好2': '喝酒\n唱歌'}
Mappings(映射)
import yaml

document = """
爱好1: 喝酒
爱好2: 唱歌
"""
res = yaml.load(document, Loader=yaml.Loader)
print(res)
============
{'爱好1': '喝酒', '爱好2': '唱歌'}

2. 语法锚点和引用

编程中我们通常用变量引用来解决这种问题,YAML也提供了一种类似的机制实现变量引用,它就是锚点引用(Anchors and Aliases);例如:同的数据被重复使用, 配置信息,

定义锚点&引用锚点
import yaml

document = """
key: &anchor pig
key2: *anchor
key3: *anchor
"""
'''
1. 使用 & 符号可以定义一个锚点
2. * 符号+锚点名 可以引用先前定义的锚点
'''
res = yaml.load(document, Loader=yaml.Loader)
print(res)
=================
{'key': 'pig', 'key2': 'pig', 'key3': 'pig'}
锚定映射&序列节点
import yaml

document = """
# 定义一个共享的内容
common_data: &anchor_id
  name: Common Name
  value: Common Value
 
# 使用锚定引用共享内容
nodes:
  - *anchor_id
  - *anchor_id
 
"""

'''
1. common_data: &anchor_id: 是一个锚定的名字,它指向一个映射(即键值对的集合)
2. *anchor_id 是一个别名,用来引用先前定义的那个映射
3. nodes 是一个list, 引用anchor_id
'''
res = yaml.load(document, Loader=yaml.Loader)
print(res)

=================
{'common_data': {'name': 'Common Name', 'value': 'Common Value'}, 'nodes': [{'name': 'Common Name', 'value': 'Common Value'}, {'name': 'Common Name', 'value': 'Common Value'}]}
合并映射-merge key

YAML提供了一种<<语法用于合并映射(Mappings)。它允许你将一个映射的键值对合并到另一个映射中,从而实现映射之间的继承和合并。这种语法也被称为"merge key";
提高代码的可维护性和可读性。这对于定义共享的配置或基本设置,并在派生配置中进行定制化非常有用

import yaml

document = """
base: &tmp_base
  name: John
  age: 30
extension:
  <<: *tmp_base
  age: 31
  city: New York 
"""

# 在base基础上update extension 信息

res = yaml.load(document, Loader=yaml.Loader)
print(res)
===================
{'base': {'name': 'John', 'age': 30}, 'extension': {'name': 'John', 'age': 31, 'city': 'New York'}}

3. yaml tag

AML中,标签(Tags)用于对数据进行类型标识或自定义标识。它们提供了一种扩展YAML数据模型的方式;

tag 介绍
tag说明demo
!!str标识字符串类型name: !!str John
!!int标识整数类型count: !!int 10
!!float标识浮点数类型pi: !!float 3.1415926
!!bool标识布尔类型is_valid: !!bool true
!!null标识nulldata: !!null
隐式tag隐式声明boolean: !!bool “true”
integer: !!int “3”
显式tag显式声明boolean: true
integer: 3
自定义tag
yaml tagpython type
!!nullNone
!!boolbool
!!intint or long (int in Python 3)
!!floatfloat
!!binarystr (bytes in Python 3)
!!timestampdatetime.datetime
!!omap, !!pairslist of pairs
!!setset
!!strstr or unicode (str in Python 3)
!!seqlist
!!mapdict
Python-specifictags
!!python/noneNone
!!python/boolbool
!!python/bytes(bytes in Python 3)
!!python/strstr (str in Python 3)
!!python/unicodeunicode (str in Python 3)
!!python/intint
!!python/longlong (int in Python 3)
!!python/floatfloat
!!python/complexcomplex
!!python/listlist
!!python/tupletuple
!!python/dictdict

3> yaml demo

配置文件用 .yaml 或者 .py 形式如下

1. yaml.load

import yaml

document = """
conv_001:
    op_list:
        - Conv2d
        - Conv2d
    creat_params:
        selector: 
            - F
            - F
        layer1:
            in_channels: 1
            out_channels: 1
            kernel_size: 3
            stride: 2
            padding: 1
            groups: 1
        layer2:
            in_channels: 1
            out_channels: 2
            kernel_size: 3
            stride: 4
            padding: 1
            groups: 1
    quant_params:
        data_num: 1
        inputShape: 
            - [1, 1, 224, 8]
"""

res = yaml.load(document, Loader=yaml.Loader)
print(res)
print(type(res))
=======================
{'conv_001': {'op_list': ['Conv2d', 'Conv2d'], 'creat_params': {'selector': ['F', 'F'], 'layer1': {'in_channels': 1, 'out_channels': 1, 'kernel_size': 3, 'stride': 2, 'padding': 1, 'groups': 1}, 'layer2': {'in_channels': 1, 'out_channels': 2, 'kernel_size': 3, 'stride': 4, 'padding': 1, 'groups': 1}}, 'quant_params': {'data_num': 1, 'inputShape': [[1, 1, 224, 8]]}}}
<class 'dict'>

2. yaml.load Unicode&yaml.Loader

使用 Loader=yaml.Loader 实现Unicode

import yaml

document = """
姓名: 小明,
爱好:
    - 喝酒
    - 唱歌
    - 赌牌
    - 打游戏
"""

res = yaml.load(document, Loader=yaml.Loader)
print(res)
print(type(res))

3. yaml.dump&Unicode

import yaml
import os

document = """
姓名: 小明,
爱好:
    - 喝酒
    - 唱歌
    - 赌牌
    - 打游戏
"""

res = yaml.load(document, Loader=yaml.Loader)
document_name = f'document.yaml'
with open(document_name, 'w') as file:
    yaml.dump(res, file, default_flow_style=False, encoding='utf-8', allow_unicode=True)
'''
数据中包含中文等 Unicode 字符,yaml.dump() 会将它们编码成不可读的表示方式。为了解决这个问题,
可以添加三个关键字参数,使中文等 Unicode 字符以可读形式保存,default_flow_style, encoding, allow_unicode
'''
print(os.path.exists(document_name))
with open(document_name, 'r') as f:
    res_load = yaml.load(f, Loader=yaml.Loader)
print(res_load)
===================
True
{'姓名': '小明,', '爱好': ['喝酒', '唱歌', '赌牌', '打游戏']}

4. yaml.load_all

aml文档中,使用 — 符号可以分段。对于带有分段的Yaml文档,使用 yaml.load() 函数会报错,需要使用 yaml.load_all() 函数;

import yaml

document = """
姓名: 小明,
爱好:
    - 喝酒
    - 唱歌
    - 赌牌
    - 打游戏
---
姓名: 小红,
爱好:
    - 写字
    - 看书
"""

res = yaml.load_all(document, Loader=yaml.Loader)
print(type(res))
for i in res:
    print(i)
====================
<class 'generator'>
{'姓名': '小明,', '爱好': ['喝酒', '唱歌', '赌牌', '打游戏']}
{'姓名': '小红,', '爱好': ['写字', '看书']}

5. yaml 与编码对象class

import yaml

class Anmails:
    def __init__(self, name, likes):
        self.name = name
        self.likes = likes
    def __repr__(self):
        return f'{self.__class__.__name__}(name={self.name}, like={self.likes})'
    def like(self):
        print(f'我是{self.name},我喜欢{str(self.likes)}! ')

to_do = Anmails('猪', ['喝酒', '唱歌', '赌牌', '打游戏'])
document = yaml.dump(to_do)
like_A = yaml.load(document, Loader=yaml.Loader)
print(yaml.dump(to_do))
print(like_A)
print(type(like_A))
like_A.like()
=======================
!!python/object:__main__.Anmails
likes:
- "\u559D\u9152"
- "\u5531\u6B4C"
- "\u8D4C\u724C"
- "\u6253\u6E38\u620F"
name: "\u732A"

Anmails(name=猪, like=['喝酒', '唱歌', '赌牌', '打游戏'])
<class '__main__.Anmails'>
我是猪,我喜欢['喝酒', '唱歌', '赌牌', '打游戏']!

6. yaml 多个编码对象class


import yaml

class Anmails:
    def __init__(self, name, likes):
        self.name = name
        self.likes = likes
    def __repr__(self):
        return f'{self.__class__.__name__}(name={self.name}, like={self.likes})'
    def like(self):
        print(f'我是{self.name},我喜欢{str(self.likes)}! ')

to_do1 = Anmails('猪', ['喝酒', '唱歌', '赌牌', '打游戏'])
to_do2 = Anmails('de-lovely', ['写字', '看书'])
document_name = r'document.yaml'
with open(document_name, 'w') as f:
    yaml.dump_all([to_do1, to_do2], f, default_flow_style=False, encoding='utf-8', allow_unicode=True)


==============
document.yaml:
!!python/object:__main__.Anmails
likes:
- 喝酒
- 唱歌
- 赌牌
- 打游戏
name: 猪
--- !!python/object:__main__.Anmails
likes:
- 写字
- 看书
name: de-lovely

7. yaml.safe_load

import yaml

document_name = 'document.yaml'
with open(document_name, 'r') as f:
    # case_params = yaml.load(f, Loader=yaml.Loader)
    case_params = yaml.safe_load(f)
print(case_params)

#修改参数
case_params['conv_001']['creat_params']['layer1']['groups'] = 2
case_params['conv_001']['op_list'][0] = 'Conv3d'
#保存参数
with open('document_currect.yaml', 'w') as file:
    yaml.dump(case_params, file)

在这里插入图片描述

4> yaml 三大组件

1. 构造器、表示器、解析器 介绍
组件功能描述
Constructors(构造器)用于将 YAML 数据解析为 Python 对象的组件,将 YAML 数据的不同类型转换为相应的 Python 对象。PyYAML 提供了一些内置的构造器,用于处理常见的数据类型,如字符串、整数、浮点数、布尔值等。同时,你也可以自定义构造器,以便将 YAML 数据解析为自定义的 Python 类型。通过注册构造器,你可以扩展 PyYAML 的解析功能,使其能够处理更多的数据类型;
Representers(表示器)与构造器相反,Representers 是用于将 Python 对象表示为 YAML 数据的组件,它们负责将 Python 对象转换为 YAML 中的相应表示形式PyYAML 提供了一些内置的表示器,用于处理常见的 Python 对象类型,如字符串、整数、浮点数、布尔值等。同时,你也可以自定义表示器,以便将自定义的 Python 类型表示为 YAML 数据。通过注册表示器,你可以定制 PyYAML 的转储功能,使其能够生成符合特定需求的 YAML 数据。
Resolvers(解析器)Resolvers 是用于解析 YAML 数据中的标签(Tags)的组件,它们负责识别标签并将其映射到相应的构造器和表示器PyYAML 提供了内置的标签解析器,用于处理常见的标准类型。同时,你也可以自定义解析器,以便识别和处理自定义的标签。通过注册解析器,你可以扩展 PyYAML 的标签识别功能,使其能够处理更多的数据类型和标签;
2. 构造&转存
import yaml

class Introduce(yaml.YAMLObject):
    yaml_tag = u'!Introduce'

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

    def __repr__(self):
        return f'{self.__class__.__name__}(name={self.name}, {self.likes})'


document = """
!Introduce
name: xiaoming
likes:
    - games
"""
'''
1. !Introduce: 定义一个YAML标签用于解析和生成Monster类型数据
2. yaml.dump(res): 转储Monster对象为YAML格式数据
'''
res = yaml.load(document, Loader=yaml.Loader)
print(res)
print(type(res))
document_cp = yaml.dump(res)
print(document_cp)
=================
Introduce(name=xiaoming, ['games'])
<class '__main__.Introduce'>
!Introduce
likes:
- games
name: xiaoming
3. 序列化构造器
import yaml

class Dice(tuple):
    def __new__(cls, a, b):
        return tuple.__new__(cls, [a, b])

    def __repr__(self):
        return "Dice(%s,%s)" % self

def dice_representer(dumper, data):
    return dumper.represent_scalar(u'!dice', u'%sd%s' % data)

yaml.add_representer(Dice, dice_representer)
res = yaml.dump(Dice(3,6))
print(res)
============
!dice '3d6'


无:# yaml.add_representer(Dice, dice_representer)
=========================
!!python/object/new:__main__.Dice
- !!python/tuple
  - 3
  - 6
4. 自定义构造器
import yaml

class Dice(tuple):
    def __new__(cls, a, b):
        return tuple.__new__(cls, [a, b])

    def __repr__(self):
        return "Dice(%s,%s)" % self

def dice_representer(dumper, data):
    return dumper.represent_scalar(u'!dice', u'%sd%s' % data)

def dice_constructor(loader, node):
    value = loader.construct_scalar(node)
    a, b = map(int, value.split('d'))
    return Dice(a, b)

yaml.add_constructor(u'!dice', dice_constructor)

res = yaml.load("initial hit points: !dice 8d4", yaml.Loader)
print(res)
==========
{'initial hit points': Dice(8,4)}

5> yaml引用环境变量

import yaml
import os

def render_env_constructor(loader, node):
    value = loader.construct_scalar(node)
    return os.path.expandvars(value)

yaml.SafeLoader.add_constructor('!ENV', render_env_constructor)

os.environ["a"]="111"
os.environ["b"]="222"
res = yaml.safe_load("test: !ENV a=${a}, b=$b")
#加载YAML时自动替换了标签!ENV标识标量的环境变量占位符
print(res)
=======
{'test': 'a=111, b=222'}

环境变量通常都是字符串形式。如果你使用了数字、布尔等其他类型,需要解析后手动转换。
os.path.expandvars是一个内置函数,用于展开字符串中的环境变量。它会在目标字符串中查找形式为 V A R 或 VAR或 VAR{VAR}的环境变量引用,并将其替换为响应的环境变量的值。如果找不到匹配的环境变量,那么引用保持不变

6> libyaml

libyaml介绍
libyaml库libyaml是一个独立的C库,用于处理 yaml数据的解析和生成。Pyyaml 可以使用 LibYAML 作为其解析和生成 yaml 数据的底层引擎;
特点LibYAML 具有高性能、低内存占用、加速 yaml数据处理
组件提供 CLoader 和 CDumper 两个组件用来集成 LibYAML;
CLoader: PyYAML 的解析器(Loader)的C扩展版本
CDumper: PyYAML的生成器(Dumper)的C扩展版本
CLoader和CDumper优势1. 通过与LibYAML的集成,提供了更高效的解析和生成功能;
2. 处理大型YAML数据时获得更好的性能和效率

7> FAQ

1. yaml.safe_load&load区别

load: Loader支持加载任意的Python对象,可能导致执行任意 Python 代码
safe_load:SafeLoader 限制了加载过程中执行的操作,只允许加载基本类型的对象,如字符串、整数、列表和字典等;当你处理来自不受信任的源或不确定性的 YAML 文件时,特别是从外部来源加载时,使用 SafeLoader 是一个良好的实践,可以提高安全性并防止可能的代码注入或其他潜在的安全问题

三:yapf

1> yapf 介绍

yapf -r -i  *_file_path.py

以下包有没有可以连接mysql的:absl-py 1.3.0 aiohttp 3.8.3 aiosignal 1.3.1 antlr4-python3-runtime 4.8 async-timeout 4.0.2 attrs 22.1.0 cachetools 5.2.0 certifi 2022.9.24 charset-normalizer 2.0.12 click 8.1.3 commonmark 0.9.1 datasets 2.3.2 dill 0.3.5.1 filelock 3.8.0 fire 0.4.0 Flask 2.1.2 fonttools 4.38.0 frozenlist 1.3.3 fsspec 2022.11.0 future 0.18.2 google-auth 2.14.1 google-auth-oauthlib 0.4.6 grpcio 1.50.0 huggingface-hub 0.11.0 idna 3.4 importlib-metadata 5.0.0 itsdangerous 2.1.2 jieba 0.42.1 Jinja2 3.1.2 joblib 1.2.0 keybert 0.7.0 lxml 4.9.1 Markdown 3.4.1 MarkupSafe 2.1.1 multidict 6.0.2 multiprocess 0.70.13 networkx 2.8.8 nltk 3.7 numpy 1.20.3 oauthlib 3.2.2 omegaconf 2.1.1 opencv-python 4.6.0.66 opencv-python-headless 4.6.0.66 packaging 21.3 pandas 1.5.2 pdf2docx 0.5.6 Pillow 9.3.0 pip 21.1.3 protobuf 3.20.3 pyarrow 10.0.0 pyasn1 0.4.8 pyasn1-modules 0.2.8 pyDeprecate 0.3.1 Pygments 2.13.0 PyMuPDF 1.21.0 pyparsing 3.0.9 python-dateutil 2.8.2 python-docx 0.8.11 pytorch-crf 0.7.2 pytorch-lightning 1.5.6 pytz 2022.6 PyYAML 6.0 regex 2021.11.10 requests 2.26.0 requests-oauthlib 1.3.1 responses 0.18.0 rich 12.6.0 rsa 4.9 sacremoses 0.0.53 scikit-learn 1.1.3 scipy 1.9.3 sentence-transformers 2.2.2 sentencepiece 0.1.97 setuptools 57.0.0 six 1.16.0 tensorboard 2.11.0 tensorboard-data-server 0.6.1 tensorboard-plugin-wit 1.8.1 termcolor 2.1.1 textrank4zh 0.3 threadpoolctl 3.1.0 tokenizers 0.10.3 torch 1.10.1+cu111 torchaudio 0.10.1+rocm4.1 torchmetrics 0.10.3 torchvision 0.11.2+cu111 tqdm 4.64.1 transformers 4.12.5 typing-extensions 4.4.0 urllib3 1.26.12 Werkzeug 2.2.2 wheel 0.36.2 xxhash 3.1.0 yarl 1.8.1 zhon 1.1.5 zipp 3.10.0
05-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

45度看我

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

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

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

打赏作者

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

抵扣说明:

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

余额充值