第一章:数据结构和算法

第一章:数据结构和算法 — python3-cookbook 3.0.0 文档

1.1 将序列分解为单独的变量

问题:一个包含N个元素的元组或序列,将它里面的值解压后同时赋值给N个变量

解决:任何可迭代对象都可以通过一个简单的赋值操作分解为单独变量,要求变量综述和结构必须与序列吻合,数量不匹配会报错

# 元组
>>> point = (1,2)
>>> x,y = p
>>> x,y
(1, 2)
>>> x
1
>>> y
2
# 列表
>>> data = [1,(1,2),"ss"]
>>> x,y,z = data
>>> x,y,z
(1, (1, 2), 'ss')
>>> x
1
>>> y
(1, 2)
>>> z
'ss'
# 字典
>>> dict = {3:'a', 4:'b'}
>>> x,y=dict
>>> x
3
>>> y
4
# 字符串
>>> str = "hello"
>>> a,b,c,d,e = str
>>> a
'h'
>>> b
'e'
>>> c
'l'
# 文件对象,迭代器,生成器都可以
# 不能只解压一部分,可以使用任意变量名占位

1.2 解压可迭代对象赋值给多个变量

问题:可迭代对象元素个数超过变量个数,抛出ValueError,从这个对象中解压出N个元素

解决:使用星号表达式

>>> data = [1,2,3,4,5,6,7,8,9]
>>> a,b, *_,d = data
>>> a
1
>>> b
2
>>> d
9
>>> _  # 星号解压的一定是列表类型
[3, 4, 5, 6, 7, 8]

1.3 保留最后N个元素

问题:迭代操作或者其他操作,怎么保留最后有限几个元素的历史记录

解决: 使用collections.deque,双向队列

>>> from collections import deque
>>> q = deque(maxlen=3) # 可指定队列最大长度
>>> q.append(1)
>>> q.appendleft(2)
>>> q.append(3)
>>> q
deque([2, 1, 3], maxlen=3)
>>> q.append(4)
>>> q
deque([1, 3, 4], maxlen=3)
>>> q.pop()
4
>>> q
deque([1, 3], maxlen=3)
>>> q.popleft()
1
>>> q
deque([3], maxlen=3)

1.4 查找最大或最小的N个元素

问题:从一个集合中获得最大或最小的N个元素列表

解决:使用heapq模块的nlargest()和nsmallest()函数

>>> import heapq
>>> nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
>>> print(heapq.nlargest(3, nums))
[42, 37, 23]
>>> print(heapq.nsmallest(3, nums))
[-4, 1, 2]
>>> portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]
>>> cheap = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])
>>> cheap
[{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]
>>> expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
>>> expensive
[{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]

heapq的heapify函数将列表转化为堆,进行堆排序,首位元素永远是最小的元素,使用heappop函数得到下一个最小元素。

查找唯一的最大或最小元素,使用min(), max()效率高;当N与集合大小接近,先排序,在切片效率高;介于中间时使用nlargest或nsmallest。

1.5 实现一个优先级队列

问题:实现一个按优先级排序的队列,且在队列上每次pop返回优先级最高的元素

解决:使用heapq实现优先级队列

>>> class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        # 使用(-priority, self._index, item)元组,优先级使用负数能使元素优先级从高到低,因为                
        # heappop每次返回的是最小的元素,使用_index是保证在优先级相同的情况下,先插入的排序在前
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]
>>> class Item:
	def __init__(self, name):
		self.name = name
	def __repr__(self):
		return 'Item({!r})'.format(self.name)
>>> q = PriorityQueue()
>>> q.push(Item('foo'),1)
>>> q.push(Item('bar'), 5)
>>> q.push(Item('spam'), 4)
>>> q.push(Item('grok'), 1)
>>> q._queue
[(-5, 1, Item('bar')), (-1, 0, Item('foo')), (-4, 2, Item('spam')), (-1, 3, Item('grok'))]
>>> q.pop()
Item('bar')
>>> q.pop()
Item('spam')
>>> q.pop()
Item('foo')
>>> q.pop()
Item('grok')

1.6 字典中的键映射多个值

问题:实现一个键对应多个值的字典

解决:字典是键值对一一对应,如果实现一个键多个值,需要将多个值放在列表或者集合中,

如果想保持插入顺序则使用列表,如果想去重则使用集合。

使用collections中的defaultdict构造字典

>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> d['a'].append(1)
>>> d['a'].append(2)
>>> d['a'].append(3)
>>> d['b'].append(4)
>>> d['b'].append(5)
>>> d['b'].append(6)
>>> d
defaultdict(<class 'list'>, {'a': [1, 2, 3], 'b': [4, 5, 6]})

1.7 字典排序

问题:创建一个字典,在迭代或序列化字典时控制元素的顺序

解决:使用collections中的OrderedDict,在迭代操作时保持元素被插入时的顺序。

>>> from collections import OrderedDict
>>> d = OrderedDict()
>>> d['foo'] = 1
>>> d['bar'] = 2
>>> d['spam'] = 3
>>> d['grok'] = 4
>>> d
OrderedDict([('foo', 1), ('bar', 2), ('spam', 3), ('grok', 4)])
>>> for key in d:
    print(key, d[key])
foo 1
bar 2
spam 3
grok 4
# 精确控制JSON编码后字段的顺序
>>> import json
>>> json.dumps(d)
'{"foo": 1, "bar": 2, "spam": 3, "grok": 4}'

OrderedDict使用根据键插入顺序排序的双向链表,新元素插入会放在链表尾部,已经存在的键的赋值不会改变顺序,OrderedDict的大小是dict的两倍。

1.8 字典的运算

问题:在数据字典中执行一些计算操作,如最小值,最大值,排序等

解决:

>>> prices = {
    'ACME': 45.23,
    'AAPL': 612.78,
    'IBM': 205.55,
    'HPQ': 37.20,
    'FB': 10.75
}
# 使用zip将键值反转后再是引用敏,min,max,sorted函数
# zip函数创建的是一个只能访问一次的迭代器
>>> min_price = min(zip(prices.values(), prices.keys()))
>>> min_price
(10.75, 'FB')
>>> max_price = max(zip(prices.values(), prices.keys()))
>>> max_price
(612.78, 'AAPL')
>>> prices_sorted = sorted(zip(prices.values(), prices.keys()))
>>> prices_sorted
[(10.75, 'FB'), (37.2, 'HPQ'), (45.23, 'ACME'), (205.55, 'IBM'), (612.78, 'AAPL')]

1.9 查找两字典的相同点

问题:在两个字典中寻找相同点,如相同的键,值等

解决:对keys或items使用集合操作

>>> a = {
    'x' : 1,
    'y' : 2,
    'z' : 3
}
>>> b = {
    'w' : 10,
    'x' : 11,
    'y' : 2
}
>>> a.keys() & b.keys()
{'y', 'x'}
>>> a.keys() | b.keys()
{'w', 'y', 'x', 'z'}
>>> a.keys() - b.keys()
{'z'}
>>> b.keys() - a.keys()
{'w'}
>>> a.items() & b.items()
{('y', 2)}
>>> a.values() & b.values()
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    a.values() & b.values()
TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict_values'

1.10 删除序列相同元素并保持顺序

问题:在一个序列上保持元素顺序的同时消除重复的值

解决:

>>> def dedupe(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield item
            seen.add(val)

            
>>> a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
>>> list(dedupe(a, key=lambda d: (d['x'],d['y'])))
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
>>> list(dedupe(a, key=lambda d: d['x']))
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]

1.11 命名切片

问题:清理大量硬编码切片

解决:使用slice创建一个切片对象,可对切片对象进行操作

>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]
>>> a = slice(5, 50, 2)
>>> a.start
5
>>> a.stop
50
>>> a.step
2
# 使用indices(size)映射到已知大小序列上,返回三元组(start, stop, step),
# 实际就是规定了切片的终止值
>>> a.indices(10)
>>> a.start
5
>>> a.stop
10
>>> a.step
2
>>> for i in range(*a.indices(10)):
        print(i)
5
7
9
# 等同于range
>>> for i in range(5,10,2):
        print(i)

1.12 序列中出现次数最多的元素

问题:找出序列中出现次数最多的元素

解决:使用collections中的Counter类

>>> words = [
    'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
    'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
    'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
    'my', 'eyes', "you're", 'under'
]
>>> from collections import Counter
>>> word_counts = Counter(words)
>>> top_three = word_counts.most_common(3)
>>> top_three
[('eyes', 8), ('the', 5), ('look', 4)]
>>> word_counts['look']
4
>>> morewords = ['why','are','you','not','looking','in','my','eyes']
>>> word_counts.update(morewords)
>>> top_three = word_counts.most_common(3)
>>> top_three
[('eyes', 9), ('the', 5), ('look', 4)]
>>> a = Counter(words)
>>> b = Counter(morewords)
>>> a-b
Counter({'eyes': 7, 'the': 5, 'look': 4, 'into': 3, 'my': 2, 'around': 2, "don't": 1, "you're": 1, 'under': 1})
>>> a+b
Counter({'eyes': 9, 'the': 5, 'look': 4, 'my': 4, 'into': 3, 'not': 2, 'around': 2, "don't": 1, "you're": 1, 'under': 1, 'why': 1, 'are': 1, 'you': 1, 'looking': 1, 'in': 1})

1.13 通过某个关键字排序一个字典列表

问题:根据某个或某几个字典字段排序一个字典

解决:使用operator中的itemgetter函数

>>> from operator import itemgetter
>>> rows = [
    {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
    {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
    {'fname': 'Eavid', 'lname': 'Ceazley', 'uid': 1002},
    {'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
    {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
>>> sorted(rows,key=lambda r:(r['uid'],r['fname']))
[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Eavid', 'lname': 'Ceazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]
>>> sorted(rows, key=itemgetter('lname','fname'))
[{'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Eavid', 'lname': 'Ceazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}]
>>> sorted(rows,key=lambda r:r['uid'])
[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Eavid', 'lname': 'Ceazley', 'uid': 1002}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]
>>> sorted(rows, key=itemgetter('fname'))
[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}, {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, {'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, {'fname': 'Eavid', 'lname': 'Ceazley', 'uid': 1002}, {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
# lambda也可以实现同样的效果,但是itemgetter运行稍微快点
# 同样适用于min,max等
>>> min(rows, key=itemgetter('uid'))
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}

1.14 排序不支持原生比较的对象

问题:排序类型相同的对象,但是不支持原生的比较操作

解决:

>>> class User:
    def __init__(self, user_id):
        self.user_id = user_id

    def __repr__(self):
        return 'User({})'.format(self.user_id)

>>> def sort_notcompare():
	users = [User(23), User(3), User(99)]
	print(users)
	print(sorted(users, key=lambda u: u.user_id))
>>> sort_notcompare()
[User(23), User(3), User(99)]
[User(3), User(23), User(99)]
>>> from operator import attrgetter
>>> users = [User(23), User(3), User(99)]
>>> sorted(users, key=attrgetter('user_id'))
[User(3), User(23), User(99)]
# attrgetter比lambda快一些

1.15 通过某个字段将记录分组

问题:根据某个特定的字段来分组迭代访问字典或实例的序列

解决:使用itertools.groupby()函数

>>> rows = [
    {'address': '5412 N CLARK', 'date': '07/01/2012'},
    {'address': '5148 N CLARK', 'date': '07/04/2012'},
    {'address': '5800 E 58TH', 'date': '07/02/2012'},
    {'address': '2122 N CLARK', 'date': '07/03/2012'},
    {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
    {'address': '1060 W ADDISON', 'date': '07/02/2012'},
    {'address': '4801 N BROADWAY', 'date': '07/01/2012'},
    {'address': '1039 W GRANVILLE', 'date': '07/04/2012'},
]
>>> from operator import itemgetter
>>> from itertools import groupby
# 
>>> ss = sorted(rows, key=itemgetter('date'))
>>> ss
[{'address': '5412 N CLARK', 'date': '07/01/2012'}, {'address': '4801 N BROADWAY', 'date': '07/01/2012'}, {'address': '5800 E 58TH', 'date': '07/02/2012'}, {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, {'address': '1060 W ADDISON', 'date': '07/02/2012'}, {'address': '2122 N CLARK', 'date': '07/03/2012'}, {'address': '5148 N CLARK', 'date': '07/04/2012'}, {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}]
>>> rows.sort(key=itemgetter('date'))
>>> rows
[{'address': '5412 N CLARK', 'date': '07/01/2012'}, {'address': '4801 N BROADWAY', 'date': '07/01/2012'}, {'address': '5800 E 58TH', 'date': '07/02/2012'}, {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, {'address': '1060 W ADDISON', 'date': '07/02/2012'}, {'address': '2122 N CLARK', 'date': '07/03/2012'}, {'address': '5148 N CLARK', 'date': '07/04/2012'}, {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}]
# groupby只检查连续元素,必须先完成排序
>>> for date, items in groupby(rows, key=itemgetter('date')):
	print(date)
	for i in items:
		print(' ', i)

07/01/2012
  {'address': '5412 N CLARK', 'date': '07/01/2012'}
  {'address': '4801 N BROADWAY', 'date': '07/01/2012'}
07/02/2012
  {'address': '5800 E 58TH', 'date': '07/02/2012'}
  {'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}
  {'address': '1060 W ADDISON', 'date': '07/02/2012'}
07/03/2012
  {'address': '2122 N CLARK', 'date': '07/03/2012'}
07/04/2012
  {'address': '5148 N CLARK', 'date': '07/04/2012'}
  {'address': '1039 W GRANVILLE', 'date': '07/04/2012'}

1.16 过滤序列元素

问题:通过一些规则从数据序列提取需要的值或缩短序列

解决:简单的使用列表推导式

>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> [n for n in mylist if n > 0]
[1, 4, 10, 2, 3]
>>> [n for n in mylist if n < 0]
[-5, -7, -1]

对于大量数据集会占用大量内存,使用生成器表达式迭代产生过滤元素

>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1]
>>> pos = (n for n in mylist if n>0)
>>> pos
<generator object <genexpr> at 0x000001B9E4649390>
>>> list(pos)
[1, 4, 10, 2, 3]

规则复杂时使用filter函数,创建一个迭代器

>>> values = ['1', '2', '-3', '-', '4', 'N/A', '5']
>>> def is_int(val):
    try:
        x = int(val)
        return True
    except ValueError:
        return False

>>> ivals = list(filter(is_int, values))
>>> ivals
['1', '2', '-3', '4', '5']

过滤工具itertools.compress(),创建一个boolean序列,然后使用compress根据序列的truefalse选择性输出,返回的也是迭代器,需要list转换。

>>> addresses = [
    '5412 N CLARK',
    '5148 N CLARK',
    '5800 E 58TH',
    '2122 N CLARK',
    '5645 N RAVENSWOOD',
    '1060 W ADDISON',
    '4801 N BROADWAY',
    '1039 W GRANVILLE',
]
>>> counts = [ 0, 3, 10, 4, 1, 7, 6, 1]
>>> from itertools import compress
>>> more5 = [n > 5 for n in counts]
>>> more5
[False, False, True, False, False, True, True, False]
>>> list(compress(addresses, more5))
['5800 E 58TH', '1060 W ADDISON', '4801 N BROADWAY']

1.17 从字典中提取子集

问题:构造一个字典,这个字典是另外一个字典的子集

解决:简单的使用字典推导

>>> prices = {
    'ACME': 45.23,
    'AAPL': 612.78,
    'IBM': 205.55,
    'HPQ': 37.20,
    'FB': 10.75
}
>>> {key: value for key, value in prices.items() if value > 200}
{'AAPL': 612.78, 'IBM': 205.55}
>>> tech_names = {'AAPL', 'IBM', 'HPQ', 'MSFT'}
>>> {key: value for key, value in prices.items() if key in tech_names}
{'AAPL': 612.78, 'IBM': 205.55, 'HPQ': 37.2}

1.18 映射名称到序列元素

问题:不通过下标访问列表或元组中的元素,而是使用名称访问元素

解决:使用collections.nametuple(),使用一个元组对象解决,函数一个返回标准元组类型子类的一个工厂方法,传递一个类型名和需要的字段,返回一个类,然后初始化这个类,为定义的字段传地值

>>> from collections import namedtuple
>>> Subscriber = namedtuple('Subscriber', ['addr', 'joined'])
>>> sub = Subscriber('jonesy@example.com', '2012-10-19')
>>> sub
Subscriber(addr='jonesy@example.com', joined='2012-10-19')
>>> sub.addr
'jonesy@example.com'
>>> sub.joined
'2012-10-19'

nametuple可以作为字典的替代,因为字典需要更多的内存存储,但是nametuple不可更改。可以使用_replace()方法,创建一个全新的nametuple取代对应字段的值。创建包含缺省值的原型元组,使用_replace()更新值。

>>> from collections import namedtuple
>>> Stock = namedtuple('Stock', ['name', 'shares', 'price'])
>>> s = Stock('ACME', 100, 123.45)
>>> s
Stock(name='ACME', shares=100, price=123.45)
>>> s.shares = 75
Traceback (most recent call last):
  File "<pyshell#121>", line 1, in <module>
    s.shares = 75
AttributeError: can't set attribute
>>> s = s._replace(shares=75)
>>> s
Stock(name='ACME', shares=75, price=123.45)
>>> stock_prototype = Stock('', 0, 0.0)
>>> def dict_to_stock(s):
    return stock_prototype._replace(**s)

>>> a = {'name': 'ACME', 'price': 123.45}
>>> dict_to_stock(a)
Stock(name='ACME', shares=0, price=123.45)

1.19 转换并同时计算数据

问题:在数据序列上执行聚集函数如sum,min,max,但是需要先转换或者过滤数据

解决:使用生成器表达式

>>> nums = [1, 2, 3, 4, 5]
>>> s = sum(x * x for x in nums)
# s = sum((x * x for x in nums)) 等价的,但是更简洁
>>> import os
>>> files = os.listdir('dirname')
>>> if any(name.endswith('.py') for name in files):
>>>     print('There be python!')
>>> else:
>>>     print('Sorry, no python.')
>>> s = ('ACME', 50, 123.45)
>>> print(','.join(str(x) for x in s))
ACME,50,123.45
>>> portfolio = [
    {'name':'GOOG', 'shares': 50},
    {'name':'YHOO', 'shares': 75},
    {'name':'AOL', 'shares': 20},
    {'name':'SCOX', 'shares': 65}
]
>>> min_shares = min(s['shares'] for s in portfolio)
>>> min_shares
20

1.20 合并多个字典或映射

问题:多个字典或映射,将它们从逻辑上合并为一个单一的映射后执行某些操作,比如查找值或者检查某些键是否存在

解决:使用collections中的ChainMap类

>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> from collections import ChainMap
>>> c = ChainMap(a,b)
>>> c['x']
1
>>> c['y']
2
# 如果出现重复值,第一次出现的映射值会被返回,所以先返回a的z,更新或删除也操作的第一个字典
>>> c['z']
3
>>> len(c)
3
>>> c.keys()
KeysView(ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}))
>>> list(c.keys())
['y', 'z', 'x']
>>> c.values()
ValuesView(ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4}))
>>> list(c.values())
[2, 3, 1]
# update()方法也可以实现更新,但是在原有基础上建立一个新字典,且就字典更新不会影响到update的字典,# chainmap使用原来的字典
>>> a = {'x': 1, 'z': 3 }
>>> b = {'y': 2, 'z': 4 }
>>> merged = dict(b)
>>> merged.update(a)
>>> merged['x']
1
>>> merged['y']
2
>>> merged['z']
3
>>> a['x'] = 13
>>> merged['x']
1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值