python学习汇总

1.类继承object:python3.9类不继承object默认也有这些特性

class Test(object):
    pass


test = Test()
print(dir(test))

"""
    输出:
        ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
    都是类的高级特性
"""
    

2.dir()

class Test():
    def test_test(self):
        pass


a = Test()
print(dir(a))
print((dir(a.test_test())))

"""
    输出:['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'test_test']
         ['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    可以得到类的属性和方法、方法的属性
"""

3.cls

cls配合@classmethod使用,self指类对象,cls指类本身

cls方法其他类或者函数可以直接类.方法()调用

class Person:
    def __init__(self, num):
        self.num = num
        print(self)

    @classmethod
    def age(cls):
        print(cls)
        return 777


class Obj:
    def obj(self):
        person = Person.age()
        print(person)
        Person(888)


a = Obj().obj()
"""
    输出:
         <class '__main__.Person'>    --->cls
         777
         <__main__.Person object at 0x000001EBDE074E80>    --->self

"""

4.namedtuple:具名元组

from collections import namedtuple

# City 是一个具名元组
City = namedtuple('City', 'name country population coordinates')
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))


"""
    City是一个类
    tokyo是类实例
"""

5.yield简单理解

带有 yield 的函数在 Python 中被称之为 generator(生成器)


def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))


"""
    输出:
         starting...
         4    --第一次运行返回4,结束运行返回值被打印
         ********************
         res: None    --第二次运行,next(g) == g.send(None),所以res = None
         4    --打印完res后,进入while循环,运行到yield结束,返回4
"""
def gen(num):    # python 解释器转换代码为字节码时,视作yield函数为生成器
    while num > 0:
        tem = yield num
        if tem is not None:
            num = tem
        num -= 1

g = gen(5)    # 实例化为生成器对象

first = next(g)    # 执行一次迭代对象
print(f"first: {first}")    # 5

# next(g) == g.send(None)
# tem = 10,并且执行后面代码
print(f"send: {g.send(10)}")    # 9

for i in g:
    print(i)    # 8, 7, ... , 1
# num执行-1后,进入while循环并且运行到yield结束

6.isinstance()

判断对象是否为哪一类型,返回布尔值。考虑继承关系

x = isinstance("Hello", (float, int, str, list, dict, tuple))
print(x)

y = isinstance("hello", tuple)
print(y)


"""
    输出:
         True
         Flase
"""

7.not>and>or优先级

print(not 0 or 1 and 0)
print(1 and 0)
print(1 or 0)

8.解决循环引用报错most likely due to a circular import

使用延迟引用 

python解决循环引用问题 - 简书当项目中的模块过多,或功能划分不够清晰时会出现循环引用的问题,如下 有两个模块moduleA 和 moduleB: 这种情况下就会出现以下的错误 : 这就是循环引用导致的 导...icon-default.png?t=N7T8https://www.jianshu.com/p/a1e91cc53b07

 9.初始化类且不 __init__初始化

class MyClass(object):
    init = False
    def __init__(self):
        print 'init called!'
        self.init = True
    def hello(self):
        print 'hello world!'


class Empty(object):
    pass


>>> a = MyClass()
init called!
>>> a.hello()
hello world!
>>> print a.init
True
>>> b = Empty()
>>> b.__class__ = MyClass    # 
>>> b.hello()
hello world!
>>> print b.init
False

10.split和rsplit

s = 'a.b.c'
res = s.split('.', 1)
res
// ['a', 'b.c']

s = 'a.b.c'
res = s.rsplit('.', 1)
res
// ['a.b', 'c']
// 类似split,区别为从结尾位置开始计数

11.enumerate(sequence, [start=0])

函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中

>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 小标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

12.反射机制 对于任意类、对象知道和调用它的所有属性和方法

  1. hasattr():函数用于判断对象是否包含对应的属性
  2. getattr(a, b, c):函数返回a对象b属性的值,默认返回c

判断模块是否包含对应类

module = importlib.import_module("tasks." + login_dict["function"])  # 导入模块
if not hasattr(module, "RunTask"):
    logger.error(f"【%s】未找到RunTask类,跳过当前注册,请检查" % login_dict["function"])
    continue

13.importlib模块实现动态导包

import importlib

m1 = importlib.import_module('example.submodule')
print(m1)

m2 = importlib.import_module('.submodule', package='example')
print(m2)

print(m1 is m2)
# import_module() 的返回值是导入创建的模块对象

14.__getattr__

python里的一个内建函数,当调用的属性或者方法不存在时,该方法会被调用

15.__repr__

方法定义了实例化对象的输出信息

16.正则

re.match() 返回第一个匹配结果,从头匹配

re.search() 返回第一个匹配结果,从任意位置匹配

re.findall() 返回列表形式所有匹配结果

match = re.search("我是(.*?)人", "我是中国人", 标识符)
match.group(0)    # 正则表达式中符合条件字符串
match.group(1)    # 正则表达式中第一个()中字符串

输出:我是中国人
输出:中国

17.decode、encode

unicode类型.decode("utf8")
"""机器可读字节 -> utf8类型"""

utf8编码类型.encode("utf8")
"""utf8类型 -> 机器可读字节"""

18.exec

exec 执行储存在字符串或文件中的 Python 语句,比如动态导包

exec("import " + each_third_package_value.CheckName)    # 参数化导入包

19.命令行参数

1. 添加参数

# 启动脚本时,添加参数
if len(sys.argv) < 2:
    with open("input_arg.json", mode="r") as fp:
        content = fp.read()

    sys.argv.append(f"--input-argument={content}")

>>> sys.argv
# 输出
['C:/file/demo.py', '--input-argument={\n  "input_xml_path": "C:/file/in.xml",\n  "out_xml_path": "C:/file/out.xml",\n  "is_developer_mode": true,\n  "user-agent": "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko"\n}']

2.接受参数

1. 实例化对象
2. 添加获取的命令行参数 --input-argument
3. parser.parse_args() 使生效
4. args.input_argument 获取对应参数
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input-argument", help="输入参数")
args = parser.parse_args()
input_argument_str = args.input_argument
input_argument_dict = json.loads(input_argument_str)

>>> input_argument_str
# 输出
'{\n  "input_xml_path": "C:/file/in.xml",\n  "out_xml_path": "C:/file/out.xml",\n  "is_developer_mode": true,\n  "user-agent": "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko"\n}'

20.xml、dict转换

xmltodict.parse       xml -> dict

xmltodict.unparse   dict -> xml

21.subprocess 待补充

22.dict补充

3.7版本字典有序,在插入键值对时保存键的顺序

实现有序字典的方式是通过哈希表和维护一个额外的数据结构(链表或跳表)来记录插入顺序。这样就可以在字典内部维护元素的有序性。其查找和访问操作仍然具有常数时间复杂度 O(1)

def test():
    return 777


dict_test = {
    "name": test()
}

>> dict_test
# 输出
{"name": 777}

# 获取字典第一个key值
next(iter(字典))

23.花活,大受震撼

function = getattr(self, f"_start_{browser_type}_browser")
function()

24.两种实现单例模式方法,待补充

class BrowserBase(metaclass=Singleton):  # 用元类实现单例模式
    """
    浏览器基类,存放浏览器对象
    """

    def __init__(self):
        self.driver: WebDriver = None  # 浏览器对象 # noqa
        self.browser = None  # 浏览器名称
        self.is_auto_popup = True  # 是否开启弹窗管理,默认是
        self.is_auto_switch_frame = True  # 是否自动切换frame,默认是
        self._implicitly_wait = None
class BehaviourBase(ElementBase, PageBase):
    """
    行为基类,组合元素基类中的方法
    """

    def __init__(self):
        # ElementBase, PageBase 的 __init__都是BrowserBase的
        BrowserBase.__init__(self)
        self.get_new_browser()
        self.timeout = 10

browser_base = BehaviourBase()  # type: BehaviourBase

25.split,执行后返回list

str.split(' ', 1 ) 返回已空格为分隔符的list

str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
print str.split( );       # 以空格为分隔符,有几个空隔几次
print str.split(' ', 1 ); # 以空格为分隔符,只在第一个空隔断


>>> ['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
>>> ['Line1-abcdef', '\nLine2-abc \nLine4-abcd']    # 只分割成两个

26.装饰器

闭包:能够读取其他函数内部变量的函数

一般用法

project_path = os.path.dirname(os.path.dirname(__file__))  # 路径
ocr_path = project_path + os.sep + "ocr"


def switch_path(func):
    """切换到ocr,执行完函数后返回"""

    @wraps(func)    # 使func.__name__ 返回函数名
    def wrapper(*agrs, **kwargs):
        if not os.path.exists(ocr_path):
            os.makedirs(ocr_path)
        workpath = os.getcwd()  # 获取当前工作目录,后续切回
        os.chdir(ocr_path)  # 切换工作目录至ocr
        res = func(*agrs, **kwargs)
        os.chdir(workpath)
        return res

    return wrapper

高级用法

对装饰器优化,实现record执行其他函数

# 在增加一层函数
from functools import wraps
import time
from random import randint

def record(output):
    def use_time(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            st_time = time.time()
            result = func(*args,**kwargs)
            end_time = time.time()
#             print(f'{func.__name__}函数use_time:{end_time-st_time}s')
            output(func.__name__, end_time-st_time)
            return result
        return wrapper
    return use_time


def write_log(name,content):
    with open('./time.log','a')as f:
        f.write(f'{name}耗时:{content}\r\n') # \r\n 换行
        
# 只需要将装饰器改为@record(write_log)
@record(write_log)
def foo():
    time.sleep(randint(2,5))

 示例:

def set_temporary_attr_value(attr, value, *, obj=None):
    """
    临时改变某个类属性的值,函数运行完毕之后恢复
    Args:
        attr: 类属性名
        value: 属性值
        obj: 需要修改属性的对象

    Returns:

    """

    def handler(func):
        def inner(self, *args, **kwargs):
            obj_ = obj if obj is not None else self
            if not hasattr(obj_, attr):
                raise ValueError(f"对象:{obj_.__class__.__name__} 缺失属性: {attr}")
            his_value = getattr(obj_, attr)
            setattr(obj_, attr, value)
            try:
                res = func(self, *args, **kwargs)
            finally:
                setattr(obj_, attr, his_value)
            return res

        return inner

    return handler

 27.多个装饰器执行顺序

​​​​​​【由浅入深】例解python装饰器执行顺序_shahuzi的博客-CSDN博客_python装饰器调用顺序

 多个装饰器执行顺序:1. 装饰器在使用于func函数时,就会实例化,dec2 > dec1。2. 执行func()时,逐个闭包dec1进入wrapper执行,然后dec2进入wrapper执行,dec1>dec2

@dec1

@dec2

def func(): pass

func()

@staticmethod
@max_try(3)
def test():
    pass

直接运行:在装饰器使用时就运行,直到wrapper

如果实例化Training:再进入wrapper运行,直至结束逐个闭包

def timing(status='Train'):
    print('this is timing')

    def dec(func):
        print('this is dec in timing')

        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            func1 = func(*args, **kwargs)
            print('[%s] time: %.3f s ' % (status, time.time() - start))
            return func1

        return wrapper

    return dec


@timing(status='Train')
def Training():
    time.sleep(3)

# 直接运行返回
# this is timing
# this is dec in timing

Training()
# this is timing
# this is dec in timing
# [Train] time: 3.015 s

 28.字典.setdefault()

aaa = dict.get(key, [])

aaa.appent(item)

dict[key] = aaa

======> 如果字典有key,则返回值并且append进去;没有key,则新增key和默认值,再弹出值,append进值中

dict.setdefault(key, []).append(item)

# table_info.setdefault(real_sm, "0") 返回real_sm键对应的值。如果不存在键,则update设置默认值,再返回real_sm键对应的值

table_info[real_sm] = add(table_info.setdefault(real_sm, 0), 777)

29.字典.update(dict)

将字典键值对添加到另一个字典中,如果键冲突,就已最后添加的值为准

30.bisect 库

bisect --- 数组二分查找算法 — Python 3.10.7 文档

bisect.bisect_right(axlo=0hi=len(a)*key=None)

x :对a遍历,和a进行比较,相等时右优先

lo=0hi=len(a) : 比较范围

key : 从数组的每个元素中提取比较键

def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
    i = bisect(breakpoints, score)    # 等同于 bisect.bisect_right,获取score下标
    return grades[i]    # 返回成绩

>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
['F', 'A', 'C', 'C', 'B', 'A', 'A']

31.set 集合 

a | b 并集,a & b 交集,a - b 差集

32.functools.patical 冻结参数

def tag(name, *content, cls=None, **attrs):
"""生成一个或多个HTML标签"""
    if cls is not None:
        attrs['class'] = cls
    if attrs:
        attr_str = ''.join(' %s="%s"' % (attr, value) for attr, value in sorted(attrs.items()))
    else:
        attr_str = ''
    if content:
        return '\n'.join('<%s%s>%s</%s>' %(name, attr_str, c, name) for c in content)
    else:
        return '<%s%s />' % (name, attr_str)
>>> tag
<function tag at 0x10206d1e0>


from functools import partial

picture = partial(tag, 'img', cls='pic-frame')
>>> picture(src='wumpus.jpeg')
'<img class="pic-frame" src="wumpus.jpeg" />'
>>> picture
functools.partial(<function tag at 0x10206d1e0>, 'img', cls='pic-frame')

33.解决数组越界思考

popup.local_popups[-1].get("keyword", "") == "777" if popup.local_popups else False

34. 对不可变对象拼接、做增量赋值

对 += 或 *= 所做的增量赋值来说,如果左边的变量绑定的是不可变对象,会创建新对象;如果是可变对象,会就地修改。
aaa = (1, 2)
print(id(aaa))  # 16365328
aaa += (777, )  # s.__iadd__(s2) s.__add__(s2)  元组可以实现拼接、就地拼接
print(aaa)      # (1, 2, 777)
print(id(aaa))  # 21765496

35.find() index()

可遍历对象.find(str, beg=0, end=len(string))

可遍历对象.index(str, beg=0, end=len(string))

index查找不到返回ValueError,find查找不到不报错返回-1

36.type运用

begin、step都是数字类型
type(self.begin + self.step)(self.begin)

type对象后得到数字类型,然后通过类型实例化本身

先做加法运算,然后使用计算结果的类型强制转换生成的结果

37.***标准库中的生成器函数***

《流畅的python》--14.9 标准库中的生成器函数

 38.浅复制

l1 = [111, 777]
l2 = l1[:]  # 对l1做浅复制
l2 is l1  # False

l3 = [3, [66, 55, 44], (7, 8, 9)]
l4 = l3[:]
l3 is l4  # False
l3[1] is l4[1]  # True

 需注意类实例化2次,不会指向一个引用

通常使用 None 作为接收可变值的参数的默认值
class TwilightBus:
    """让乘客销声匿迹的校车"""
    def __init__(self, passengers=[]):
        self.passengers = passengers

    def pick(self, name):
       self.passengers.append(name)

    def drop(self, name):
     self.passengers.remove(name)


aaa = TwilightBus()
bbb = TwilightBus()
aaa is bbb  # False
aaa.passengers is bbb.passengers  # True
aaa.pick(777)
bbb.passengers  # [777]


class TwilightBus2:
    """让乘客销声匿迹的校车"""
    def __init__(self, passengers=None):
        if passengers is None:
            self.passengers = []
        else:
            self.passengers = list(passengers)  # 实现防御可变参数

    def pick(self, name):
       self.passengers.append(name)

    def drop(self, name):
     self.passengers.remove(name)


aaa = TwilightBus2()
bbb = TwilightBus2()
aaa.passengers is bbb.passengers  # False
aaa.pick(777)
bbb.passengers  # []

 39.垃圾回收和弱引用

垃圾回收:每个对 象都会统计有多少引用指向自己。当引用计数归零时,对象立即就被销毁
弱引用:弱引用不会增加对象的引用数量。弱引用不会妨碍所指对象被当作垃圾回收。
a_set = {1, 3}
wref = weakref.ref(a_set)  # 对a_set弱引用,返回ref类
wref()  # {1, 3}
a_set = {3, 4}
wref  # <weakref at 0x000002C1CCB754E0; dead>
wref()  # None
WeakValueDictionary:一种可变映射,里面的值是对象的弱引用。被引用的对象在程序中的其他地方被当作垃圾回收后,对应的键会自动从 WeakValueDictionary 中删除
class Cheese:
    def __init__(self, kind):
        self.kind = kind

    def __repr__(self):
        return 'Cheese(%r)' % self.kind


stock = weakref.WeakValueDictionary()
catalog = [Cheese('Red Leicester'), Cheese('Tilsit'), Cheese('Brie'), Cheese('Parmesan')]
for cheese in catalog:
    stock[cheese.kind] = cheese

# cheese变量为列表中最后一项,仍然被引用
del catalog
sorted(stock.keys())  # ['Parmesan']

del cheese
sorted(stock.keys())  # []

set、list子类、dict子类,可以作为弱引用的目标。int、tuple实例或者子类都不能作为弱引用目标

 40.zip和zip_longest

list(zip(range(3), 'ABC', [0.0, 1.1, 2.2, 3.3]))
# 当一个可迭代对象耗尽后,它不发出警告就停止。
[(0, 'A', 0.0), (1, 'B', 1.1), (2, 'C', 2.2)]

list(zip_longest(range(3), 'ABC', [0.0, 1.1, 2.2, 3.3], fillvalue=-1))
# 当一个可迭代对象耗尽后,使用默认值(None)填充缺少值,直到所有迭代对象耗尽。
[(0, 'A', 0.0), (1, 'B', 1.1), (2, 'C', 2.2), (-1, -1, 3.3)]

 41.协程

生成器的调用方可以使用 .send(...) 方法发送数据,发送的数据会成为生成器函数中 yield 表达式的值。因此,生成器可以作为协程使用。协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值。

42.itertools.product()

返回一个笛卡尔积的迭代器

import itertools
a = (1, 2, 3)
b = ('A', 'B', 'C', 'D')
c = itertools.product(a, b)
for elem in c:
    print(elem)

43.德摩根定律

not 条件 or not 条件 == not (条件 and 条件)

44.product返回笛卡尔积

接受多个可迭代对象,返回它们的笛卡尔积

list(product([1, 2], [3, 4]))
# [(1, 3), (1, 4), (2, 3), (2, 4),]

45.islice(seq, start, end, step)对可迭代对象切片

with open(filname, "r") as fp:
    for line in islice(fp, 0, None, 2)
        yield line

46.__eq__

class Node:
    def __init__(self, key):
        self.key = key

    def __eq__(self, other):
        return self.key == other

    def __lt__(self, other):
        return self.key < other

    def __hash__(self):
        return hash(self.key)

    def __getitem__(self, item):
        return self.key[item]

    def __str__(self):
        return str(self.key)

    def __repr__(self):
        return "<%s: (%r, %r)>" % (self.__class__.__name__, self.key[0], self.key[1])


node = Node((111, 222))

print(node in [(777, 888), (111, 222)])  # True

列表中每一项都和node比较 node == 每一项,即 node.__eq__(每一项)

47.自定义元组类

class DemoTuple(tuple):
    def __new__(cls, value, setting, *args, **kwargs):
        self = super().__new__(cls, value)
        self.setting = setting
        return self


aaa = DemoTuple([1, 2], 777)
aaa.setting  # 777
isinstance(aaa, tuple)  # True

bbb = DemoTuple((1, 2), 111)
bbb.setting  # 111
isinstance(bbb, tuple)  # True

48.f-string语法

aaa = [1, 777, 2313, 33]
for i in aaa:
    print(f"{i: 5}")

"""使输出格式占用5个字符
    1
  777
 2313
   33
"""

aaa = "8"
print(f"{aaa: 0>8}")

"""用0补全8位字符串
00000008
"""

49.访问对象属性顺序

__getattribute__ > 特性(property) > 对象__dict__ > 类__dict__ > __getattr__

50.django:ConnectionProxy 代理设计模式

51.django:LazySettings 懒加载设计

52.元类

1. 子类继承父类,父类由元类创建,子类也是由元类创建

2. 在 MyBaseClass MySubClass 被定义时,元类就会调用 __new__ __init__ 方法

class MyMeta(type):
    def __new__(cls, *args, **kwargs):
        meta_obj = super(MyMeta, cls).__new__(cls, *args, **kwargs)
        print("元类实例:", cls.__name__)
        return meta_obj

    def __init__(cls, name, bases, attrs):
        print("元类初始化:", cls.__name__)


class MyBaseClass(metaclass=MyMeta):
    pass


class MySubClass(MyBaseClass):
    pass


# obj = MySubClass()
# obj2 = MyBaseClass()


"""
元类实例: MyBaseClass
元类初始化: MyBaseClass
元类实例: MySubClass
元类初始化: MySubClass
"""

53.__init_subclass__在不使用元类情况下改变子类行为

54.在遍历生成器时报错,下次再遍历只能从报错位置的下一个起

55.异步上下文管理

import asyncio
from contextlib import asynccontextmanager


@asynccontextmanager
async def async_resource1():
    print("Entering async resource 1")
    try:
        yield
    finally:
        print("Exiting async resource 1")


@asynccontextmanager
async def async_resource2():
    print("Entering async resource 2")
    try:
        yield
    finally:
        print("Exiting async resource 2")


async def main():
    async with async_resource1() as resource1, async_resource2() as resource2:
        # 在这里可以安全地使用 resource1 和 resource2
        print("Using resources")

asyncio.run(main())


"""
Entering async resource 1
Entering async resource 2
Using resources
Exiting async resource 2
Exiting async resource 1
"""

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值