Python面向对象编程随笔

Python面向对象编程

参考教程:https://www.bilibili.com/video/av8475172?p=1

面向过程与面向对象

  • 面向过程:自顶向下,用于解决计算问题或实现某种算法,与我们的思考方式一致,拿到问题,思考问题, 设计步骤,得出结果。通过函数/过程操纵表现世界的数据与状态,运行效率较高。
  • 面向对象:自底向上,把世界描绘成具有主动性的对象之间的交互,运行效率较低。

体会区别

例子:在一维地图上,有一只虫子和一只蚂蚁,每一次他们都走过一个-3,-2,2,+3,三个随机单位的距离,达到边界放弃移动,处于同一位置时,蚂蚁吃掉虫子,游戏结束。

  1. 面向过程

在这里插入图片描述

import random

ant_point = random.randint(0,20)
worm_point = random.randint(0,20)
print("蚂蚁的位置:",ant_point,",虫子的位置:",worm_point)
step = [-3,-2,2,-3]
while ant_point != worm_point:
    go_step = random.choice(step)
    if 0 < ant_point+go_step < 20:
        ant_point += go_step
    go_step = random.choice(step)
    if 0 < worm_point+go_step < 20:
        worm_point += go_step
    print("蚂蚁的位置:",ant_point,",虫子的位置:",worm_point)
  1. 面向对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bOPaHa9o-1575984138154)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\1575766888180.png)]

import random

class Sprite:
    """定义一个精灵类,是蚂蚁类和虫子类的父类,具有蚂蚁和虫子的一些共同特征"""
    step = [-3,-2,2,3]
    def __init__(self, gm, point=None):
        self.gm = gm
        if point is None:
            self.point = random.randint(0,20)
        else:
            self.point = point
    def jump(self):
        go_step = random.choice(Sprite.step)
        if 0 < self.point+go_step < 20:
            self.point += go_step

class Ant(Sprite):
    """定义一个蚂蚁类,继承Sprite类"""
    def __init__(self,gm,point=None):
        super().__init__(gm,point)
        self.gm.set_point("ant",self.point)
    def jump(self):
        super().jump()
        self.gm.set_point("ant",self.point)

class Worm(Sprite):
    """定义一个虫子类,继承Sprite类"""
    def __init__(self,gm,point=None):
        super().__init__(gm,point)
        self.gm.set_point("worm",self.point)
    def jump(self):
        super().jump()
        self.gm.set_point("worm",self.point)

class GameMap:
    def __init__(self):
        # 初始化,设置最初位置为None
        self.ant_point = None
        self.worm_point = None
    def catch(self):
        # 判断是否相遇
        print("蚂蚁的位置:",self.ant_point,";虫子的位置:",self.worm_point)
        if self.ant_point is not None and self.worm_point is not None and self.worm_point == self.ant_point:
            return True
    def set_point(self,src,point):
        if src == "worm":
            self.worm_point = point
        if src == "ant":
            self.ant_point = point

if __name__ == '__main__':
    gm = GameMap()   # 创建一个游戏地图对象
    worm = Worm(gm)
    ant = Ant(gm)
    while not gm.catch():
        worm.jump()
        ant.jump()

理解对象

  • 对象可以指自然界中的任何事物
  • 自然界中的事物的模型化
  • 对象具有自身的属性和方法
  • 对象通过实例化类产生

对象优越性

  • 封装:将模型的特征和能力打包在一起,隐藏细节,外界只能对其进行调用,不能修改

  • 继承:符合自然界的分类规律,快速的代码重用

  • 多态:子类可以继承父类的特征和能力,还可以通过自定义来修改其特征和能力【鸭子类型】

  • 组合:一个模型可以其他的模型组成

定义和使用类

1、定义方法

class 类名:
	pass

2、使用方法

# 对象 = 类名()
tc = testClass()

3、类与实例之间的关系

定义类就是建立模型,实例化类就是创建一个实例,类是一个抽象的概念,代表具有同一特征和能力的某一类事物,实例是这类事物的具体体现。

4、实例属性

在这里插入图片描述

5、类属性

  • 类属性在类定义后就存在,不需要实例化
  • 类属性使得相同类的不同实例具有相同的属性
class Tree:
	hight = 120

这样定义后所有实例化产生的的树hight都是120

6、私有属性

私有属性是在类的内部使用的属性,不能在外部对其进行修改

在这里插入图片描述

7、特殊属性

可以通过dir(类名)进行查看

特殊属性名作用
_doc_查看文档
_name_查看类名
_dict_保存实例属性及键值
_module_保存类所在的模块名
_base_查看父类

类的方法

1、定义方法

def 方法名(self,...):
	pass

其中self代表类的实例本身,在调用方法时由系统自动提供,方法定义时必须指明self参数。

2、类方法的使用

  • 在类的内部调用:self.<方法名>.(参数列表)
  • 在类分外部调用:实例名.<方法名>.(参数列表)

注:以上两种调用方法中,提供的参数列表中都不用包括self

3、构造方法及其作用

在这里插入图片描述

深入类的属性

1、类属性和实例属性重名

  • 以实例名.属性名引用时,优先引用实例属性
  • 以类名.属性名引用时,只能引用类属性

2、属性访问的特殊方法(反射)

  • 提供用字符串来操作类的属性和方法

  • 主要工具函数:

    hasattr(obj_name,'属性名')             # 测试实例是否具有某个属性
    setattr(obj_name,'属性名',值)		  # 修改obj_name中的属性值
    getattr(obj_name,'属性名')             # 获取obj_name中的属性值
    

3、属性包装(装饰器)

将方法包装成属性,以隐藏相关实现

控制属性的类型或范围

虚拟属性(有其他属性处理后得来)

三种属性操作:

  1. 可读:@property
  2. 可写:@property-name.setter
  3. 可删:@property-name.deleter

4、描述符

  • 将实现特殊协议的方法的类作为另一个类的类属性

  • 用来拦截和控制属性访问并可以重复使用

  • 协议方法

    1. _get_()
    2. _set_()
    3. _delete_()
  • 分类:

    1. 数据描述符:实现全部协议方法
    2. 非数据描述符:实现部分协议方法
    3. 所有的类成员函数都是非数据描述符
  • 同名的实例属性和非数据描述符(以方法为例)访问优先级:属性高于方法

  • 注意:只能在新式类中使用

    class NonNeg:
        def __init__(self,default=0):
            self.default = default
        def __get__(self, instance, owner):
            return self.default
        def __set__(self, instance, value):
            if value > 0:
                self.default = value
            else:
                print("不能为负值")
        def __delete__(self, instance):
            pass
    
    class Movie:
        rating = NonNeg()
        score = NonNeg()
    
    if __name__ == '__main__':
        m = Movie()
        print('rating:',m.rating)
        print('score:',m.score)
        m.rating = 80
        print('rating:', m.rating)
        m.score = -3
        print('score:', m.score)
    

5、__call__方法

​ 使实例可以当作函数直接使用

class Tst:
    def __call__(self, *args, **kwargs):
        print("call")

t = Tst()
t()

类方法和静态方法

1、静态方法

在这里插入图片描述

2、类方法

在这里插入图片描述

类的继承与方法重载

1、继承

  • 特点:

    【1】减少代码和灵活定制新类

    【2】子类具有父类的属性和方法

    【3】子类不能继承父类的私有属性和方法

    【4】子类可添加新的方法

    【5】子类可以修改父类的方法

  • 语法

    # class 类名(继承的父类名):
    class Myclass(Baseclass):
    	pass
    # class 类名(父类1,父类2,....)
    class Myclass(Baseclass1,Baseclass2):
        pass
    

2、重载

  • 语法:直接定义和父类同名的方法

  • 修改父类的方法

    【1】在重载的方法中调用父类方法

    # super().父类中的方法名
    super().start_washer()
    

    【2】同时添加相应的业务逻辑

    【3】多重继承时如何调用父类方法:按括号内顺序进行调用

    >>> class A:
    	def foo(self):
    		print('A foo')
    	
    >>> class B:
    	def foo(self):
    		print('B foo')
    
    >>> class C(A,B):
    	pass
    
    >>> c = C()
    >>> c.foo()
    A foo
    >>> class D(B,A):
    	pass
    
    >>> d = D()
    >>> d.foo()
    B foo
    

类的特殊方法

1、深入理解类

在这里插入图片描述

2、元类

类的创建和管理者(type),所有的类都是元类(type)的实例

  • 类实例化过程

    先调用_new_(),

    然后调用 _init_()

  • 自定义元类

    1. 目的:对其创建的类进行预处理
    2. 继承type
    3. 定义__new()__方法
    4. 还可以定义__init()__方法
    """为每一个类创建info()方法和company属性"""
    class MyMeta(type):
        def __init__(self,name,bases,dicts):
            print("Init Instance.")
    
        def __new__(cls,name,bases,dicts):
            dicts['info'] = lambda self:print('Djx.')
            res = type.__new__(cls,name,bases,dicts)
            res.company = "Meizi"
            return res
    
    class custom(metaclass=MyMeta):
        pass
    
    if __name__ == '__main__':
        cus = custom()
        cus.info()
        print(cus.company)
    
  • 应用元类

在这里插入图片描述

3、构造序列 ——使类成为序列

在这里插入图片描述

class MySeq:
    def __init__(self):
        self.lseq = ['I','II','III','IV']
    def __len__(self):
        return len(self.lseq)
    def __getitem__(self, key):
        if 0 <= key < 4:
            return self.lseq[key]

if __name__ == '__main__':
    m = MySeq()
    for i in range(4):
        print(m[i])

4、构造iter

在这里插入图片描述

class MyIter:
    def __init__(self,start,end):
        self.count = start
        self.end = end

    def __iter__(self):
        return self
    def __next__(self):
        if self.count < self.end:
            r = self.count
            self.count += 1
            return r
        else:
            raise StopIteration

if __name__ == '__main__':
    for i in MyIter(1,10):
        print(i)

5、可比较类

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __lt__(self, other): # 小于的比较
        return self.x < other.x
    def __gt__(self, other): # 大于的比较
        return self.y > other.y

if __name__ == '__main__':
    pa = Point(0,1)
    pb = Point(1,0)
    print(pa < pb)
    print(pa > pb)

6、构造可运算类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OoGnwjWB-1575984138162)(C:\Users\HP\AppData\Roaming\Typora\typora-user-images\1575812262374.png)]

class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y
    def __add__(self, other):
        return Point(self.x + other.x,self.y + other.y)
    def info(self):
        print(self.x,self.y)

if __name__ == '__main__':
    pa = Point(1,2)
    pb = Point(3,4)
    pc = pa + pb
    pc.info()

鸭子类型与多态

1、什么是多态

一种类型具有多种类型的能力,允许不同的对象对同一消息做出灵活的反应,以一种通用的方式对待可使用的对象,非动态语言必须通过继承和接口来实现

2、Python中的多态

通过继承实现多态(子类可以作为父类使用),子类通过重载父类的方法实现多态。

>>> class Animal:   # 父类
	def move(self):
		print('Animal is moving...')

		
>>> class Dog(Animal):   # 子类,继承Animal类
	pass

>>> def move(obj):
	obj.move()

	
>>> a = Animal()
>>> move(a)
Animal is moving...
>>> d = Dog()
>>> move(d)
Animal is moving...

>>> class Cat(Animal):
	def move(self):  # 重载
		print('Cat is moving...')

		
>>> class Sheep(Animal):
	def move(self):  # 重载
		print('Sheep is moving...')

        
>>> move(Sheep())
Sheep is moving...
>>> move(Cat())
Cat is moving...

3、动态语言与鸭子类型

在这里插入图片描述

4、多态的好处

  • 可实现开放的扩展与修改的封闭
  • 使python更具灵活性

Python与设计模式

1、设计模式

在这里插入图片描述

class SingleClass:
    def __init__(self,x=0):
        self.x = 0

sc = SingleClass()

def tsc():
    print(sc.x)
    sc.x = 10
    print(sc.x)

def tsc2():
    print(sc.x)
    sc.x = 9
    print(sc.x)

if __name__ == '__main__':
    tsc()
    tsc2()
class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_sgl'):
            cls._sgl = super().__new__(cls,*args,**kwargs)
        return cls._sgl

if __name__ == '__main__':
    sa = Singleton()
    sb = Singleton()
    print(id(sa))
    print(id(sb))

2、普通工厂模式

class Ab:
    a = 3

class Ac:
    a = 0

class MyFactory:
    def get_instance(self,ins):
        return ins()

if __name__ == '__main__':
    mf = MyFactory()
    print(type(mf.get_instance(Ab)))
    print(type(mf.get_instance(Ac)))
   
# 结果
# <class '__main__.Ab'>
# <class '__main__.Ac'>

3、策略模式

在这里插入图片描述

class Moveable:
    def move(self):
        print('moving...')

class MoveOnFeet(Moveable):
    def move(self):
        print("move on feet")

class MoveOnWheel(Moveable):
    def move(self):
        print("move on wheel")

class MoveObj:
    def set_move(self,moveable):
        self.moveable = moveable()
    def move(self):
        self.moveable.move()

if __name__ == '__main__':
    m = MoveObj()
    m.set_move(Moveable)
    m.move()
    m.set_move(MoveOnFeet)
    m.move()
    m.set_move(MoveOnWheel)
    m.move()
def movea():
    print("move a")
def moveb():
    print("move b")

class MoveObj:
    def set_move(self,moveable):
        self.moveable = moveable
    def move(self):
        self.moveable()

if __name__ == '__main__':
    m = MoveObj()
    m.set_move(movea)
    m.move()
    m.set_move(moveb)
    m.move()
   
# 结果
# move a
# move b

4、装饰模式

在这里插入图片描述

1、原理

# 例1
class BeDeco:
    def be_edit_fun(self):
        print('Source fun.')
    def be_keep_fun(self):
        print('keep fun.')

class Decorater:
    def __init__(self,dec):
        self._dec = dec()
    def be_edit_fun(self):
        print('Start...')
        self._dec.be_edit_fun()
    def be_keep_fun(self):
        self._dec.be_keep_fun()

if __name__ == '__main__':
    bd = BeDeco()
    bd.be_edit_fun()
    bd.be_keep_fun()

    dr = Decorater(BeDeco)
    dr.be_edit_fun()
    dr.be_keep_fun()
    
 # 结果
Source fun.
keep fun.
Start...
Source fun.
keep fun.
# 例2
class Water:
    def __init__(self):
        self.name = 'Water'
    def show(self):
        print(self.name)
class Deco:
    def show(self):
        print(self.name)

class Salt(Deco):
    def __init__(self,water):
        self.name = 'Salt'
        self.water = water
    def show(self):
        print(self.name)
        print(self.water.name)
class Suger(Deco):
    def __init__(self,water):
        self.name = 'Suger'
        self.water = water
    def show(self):
        print(self.name)
        print(self.water.name)

if __name__ == '__main__':
    w = Water()
    s = Suger(w)
    s.show()

    s = Salt(w)
    s.show()
    
 # 结果
Suger
Water
Salt
Water

2、类装饰器

def deco(a_class):
    class newClass:
        def __init__(self,age,color):
            self.age = age
            self.color = color
        def display(self):
            print(self.age)
            print(self.color)
    return newClass    # 必须返回新类
@deco    # 装饰器标志
"""
去掉后报错
    c = Cat(12,'black')
TypeError: __init__() takes 2 positional arguments but 3 were given
"""
class Cat:
    def __init__(self,age):
        self.age = age

    def display(self):
        print(self.age)

if __name__ == '__main__':
    c = Cat(12,'black')
    c.display()
    
# 结果
12
black

通过组合来构建复杂的对象

1、理解组合

  • 类似用各种零件组装机器
  • 零件-----基础类;机器-------包含其他类的类
  • 体现自下而上的面向对象编程方法

2、组合案例——雪人

  • 面向对象分析 ——雪人分为哪几部分

  • 抽象出基类

    1. Shape:不同角度参数的图形元素
    2. ShapeAngles:需要角度参数的图形元素
  • 实现基类

    class Shape:
        def __init__(self,cvns,points): # cvns--画布;points--位置
            self.cvns = cvns
            self.points = points
            self.pid = None
        def delete(self):  # 删除图像
            if self.pid:
                self.cvns.delete(self.pid)
    
    class ShapeAngle(Shape):
        def __init__(self,cvns,points,angles=(10,170)):
            super().__init__(cvns,points)
            self.angles = {'start':angles[0],'extent':angles[1]}
            
    
  • 实现子类

在这里插入图片描述

  1. HatTop —— 帽子顶部
  2. HatBottom ——帽子底端
  3. Face ——脸
  4. Sense —— 五官
  5. BodyOutline —— 身体轮廓
  6. Button —— 纽扣

面向对象开发实例——图形化时钟程序

1、项目描述

运用python的tkinter库开发图形化时钟程序:

  1. 时钟启动时以系统时间为当前时间
  2. 时钟有时针、分针和秒针
  3. 表盘可以切换为程序绘制的或基于图片的

2、钟表——对象分析

在这里插入图片描述

3、对象属性

  • 指针

在这里插入图片描述

  • 基本表盘
    在这里插入图片描述

  • 图像表盘

在这里插入图片描述

  • 钟表
    1. 三种类型的指针
    2. 表盘
    3. 切换表盘
  • 按钮——切换表盘

4、源码

由于对tkinter库没有深入了解,对一些内部实现未能掌握,表盘背景的更改未能实现,此源码主要为了体验面向对象编程

import time,datetime
import math
import itertools
import tkinter
import threading

def get_clock_step(base_pntr,long_pntr):
    # 获取指针坐标点
    pos = []
    for i in range(60):
        pos.append((base_pntr[0]+long_pntr*math.cos(i*math.pi/30),base_pntr[0]+long_pntr*math.sin(i*math.pi/30)))
    return pos[45:] + pos[:45]

def gen_i_pos(c_pntr,long_pntr):
    # 将坐标点包装成一个生成器
    for i,p in enumerate(get_clock_step(c_pntr,long_pntr)):
        yield i,p

class Pointer:
    def __init__(self,c_pntr,long_pntr,cvns,scale=None,super_pntr=None,width=1,fill='black'):
        # 参数说明:
        # c_pntr:表盘的中心坐标
        # long_pntr:表针长
        # cvns:画布引用
        # scale:指针行走比例
        # super_pntr:上级指针
        # width:指针粗细
        # fill:指针颜色
        self.pos_iter = itertools.cycle(gen_i_pos(c_pntr,long_pntr))
        self.scale = scale
        self.cvns = cvns
        self.crrnt_pos = self.pos_iter.__next__()[1]
        self.c_pntr = c_pntr
        self.super_pntr = super_pntr
        self.id_pntr = None
        self.width = width
        self.fill = fill

    def draw(self):
        self.id_pntr = self.cvns.create_line(self.c_pntr,self.crrnt_pos,width=self.width,fill=self.fill)

    def delete(self):
        if self.id_pntr:
            self.cvns.delete(self.id_pntr)

    def walk_step(self):
        self.delete()  # 删除上一时刻的指针
        self.draw()    # 创建当前时刻的指针
        i,self.crrnt_pos = self.pos_iter.__next__()
        if self.super_pntr and self.scale and (i+1)%self.scale == 0:
            # 判断上级指针是否需要行走
            self.super_pntr.walk_step()

    def set_start(self,steps):
        for i in range(steps - 1):
            self.pos_iter.__next__()
        self.crrnt_pos = self.pos_iter.__next__()[1]

class PlateImg:
    def __init__(self,c_pntr,clock_r,cvns,img):
        self.cvns = cvns
        self.clock_r = clock_r
        self.c_pntr = c_pntr
        self.img = img
        self.pid = None
        self.draw()

    def draw(self):
        self.im = tkinter.PhotoImage(file=self.img)
        self.pid = self.cvns.create_line(self.c_pntr,image=self.im)

    def delete(self):
        if self.pid:
            self.cvns.delete(self.pid)

    def set_img(self,img):
        self.img = img
        self.delete()
        self.draw()

class InImg(PlateImg):
    def draw(self):
        x = self.c_pntr[0]
        y = self.c_pntr[0] + self.clock_r/5
        self.im = tkinter.PhotoImage(file=self.img)
        self.pid = self.cvns.create_line(x,y,image=self.im)

class CustomPlate:
    def __init__(self,c_pntr,clock_r,cvns,imgp='patex.gif',imgi='flowersx.gif'):
        self.pi = PlateImg(c_pntr,clock_r,cvns,imgp)
        self.ii = InImg(c_pntr,clock_r,cvns,imgi)
    def set_img(self,imgp,imgi):
        self.pi.set_img(imgp)
        self.ii.set_img(imgi)
    def delete(self):
        self.pi.delete()
        self.ii.delete()

class Plate:
    def __init__(self,c_pntr,clock_r,cvns,long=10):
        self.pos_a = get_clock_step(c_pntr,clock_r-long)
        self.pos_b = get_clock_step(c_pntr,clock_r)
        self.cvns = cvns
        self.plates = []
        self.draw()
    def draw(self):
        for i,p in enumerate(zip(self.pos_a,self.pos_b)):
            width = 5 if (i+1)%5 == 0 else 3
            pid = self.cvns.create_line(*p,width=width)
            self.plates.append(pid)
    def delete(self):
        if self.plates:
            for item in self.plates:
                self.cvns.delete(item)

class MyClock:
    def __init__(self,base_pntr,clock_r,cvns):
        self.c_pntr = base_pntr
        self.clock_r = clock_r
        self.cvns = cvns
        self.plate = Plate(base_pntr,clock_r,self.cvns)
        h,m,s = self.start_time()
        self.h_pntr = Pointer(base_pntr, 3 * clock_r // 5,self.cvns,width=5,fill='blue')
        self.m_pntr = Pointer(base_pntr,4 * clock_r // 5,self.cvns,12,super_pntr=self.h_pntr)
        self.h_pntr.set_start(h * 5)
        self.m_pntr.set_start(m)
        self.h_pntr.walk_step()
        self.m_pntr.walk_step()
        self.s_pntr = Pointer(base_pntr,clock_r-5,self.cvns,60,super_pntr=self.m_pntr,fill='red')
        self.s_pntr.set_start(s)

    def chg_plate(self):
        self.plate.delete()
        if isinstance(self.plate,CustomPlate):
            self.plate = Plate(self.c_pntr,self.clock_r,self.cvns)
        else:
            self.plate = CustomPlate(self.c_pntr,self.clock_r,self.cvns)
        self.h_pntr.delete()
        self.h_pntr.draw()
        self.m_pntr.delete()
        self.m_pntr.draw()

    def set_img(self,imgp,imgi):
        if not isinstance(self.plate,CustomPlate):
            self.chg_plate()
        self.plate.set_img(imgp,imgi)
    def walk_step(self):
        self.s_pntr.walk_step()
    def start_time(self):
        crrnt_time = datetime.datetime.now()
        hour = crrnt_time.hour
        minute = crrnt_time.minute
        second = crrnt_time.second
        return hour,minute,second

class MyButton:
    def __init__(self,root,clock):
        self.clock = clock
        button = tkinter.Button(root,text="改变表盘",command=self.chg_plate)
        button.pack()

    def chg_plate(self):
        self.clock.chg_plate()

class MyTk(tkinter.Tk):
    def quit(self):
        # tkinter.Tk.StartClock.looping = False
        StartClock.looping = False
        self.quit()

class StartClock:
    looping = True
    def __init__(self,mc,root):
        self.mc = mc
        self.root = root
    def start_clock(self):
        while StartClock.looping:
            self.mc.walk_step()
            self.root.update()
            time.sleep(0.05)

if __name__ == '__main__':
    root = MyTk()
    cvns = tkinter.Canvas(root,width=400,height=400,bg='white')
    cvns.pack()
    mc = MyClock((200,200),200,cvns)
    bt = MyButton(root,mc)
    t = threading.Thread(target=StartClock(mc,root).start_clock)
    t.setDaemon(True)
    t.start()
    root.resizable(False,False)
    root.mainloop()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值