面向过程

  • 面向过程
  • 函数式编程
  • 面向对象

1.0 面向过程

所谓过程就是我们解决问题的步骤,一步步的按照流程走,有先后之分。

它呢,整个设计就好比流水线,思维上比较机械化。

1.1优缺点

  • 优点:
    • 复杂的问题流程化,将问题分解简化。
  • 缺点
    • 拓展性不好

2.0 面向对象

核心是对象。

正式的来说:

  • 对象是一个数据以及相关行为的简化的集合
  • 面向对象是功能上指向建模对象

通过数据行为方式来描述交互对象的集合

在python中,一切皆为对象。

面向对象的优缺点

优点

  • 解决程序的拓展性

缺点

  • 复杂度远高于面向过程
  • 交互是解决问题,无法准确预测结果。

类就是类别,种类

对象就是特征和技能的统一体。

类则是这一系列对象的特征和技能的结合。

对于现实世界,先有个体(即对象),才有类别;

但对于程序,必须先有类,才有对象的。

3.0 面向对象编程

OPP(object oriented programming)

其实是一种程序设计思想。OOP把对象作为程序的一个基本单元,一个对象就包含了数据和操作数据的函数。

在python中,所有数据类型都可以视为对象,同时我们也可以自定义对象。

自定义对象的数据类型就是面向对象种类(class)的概念。

Demo:

假如要处理我们的成绩。为了表示学生的成绩:

  • 面向过程的方式
stu1={'name':'tom','score'=99}
stu2={'name':'jack','score'=82}
  • 利用函数来实现
def find_score(stu):
 print(stu['name'],':',stu['score'])
  • 如果是面向对象
class student:
    def __init__(self, school,name, age ,sex):
        self.school = school
        self.name = name
        self.age = age
        self.sex = sex
    def eat(self):
        print(self.name,'is eating')
    def study(self):
        print(self.name,'is studying')
    def sleep(self):
        print(self.name,'is sleep')
stu1 = student('zucc','tom',22,'男')
stu1.eat()
#tom is eating
  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • **方法:**类中定义的函数。
  • **类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • **数据成员:**类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • **方法重写:**如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。、
  • **局部变量:**定义在方法中的变量,只作用于当前实例的类。
  • **实例变量:**在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
  • **继承:**即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • **实例化:**创建一个类的实例,类的具体对象。
  • **对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

  • 面向对象的设计思想,抽象出类,再根据类创建实例。
class className(object):
  '''dicstring'''
   class_statement

类的命名,大驼峰式

变量名称中的单词首字母大写

创建一个类

class MyFirstClass:
  pass

类的作用是一个模板。我们可以在创建实例的时候,把一些我们认为必须要绑定的属性填写进去。这时我们就通过特殊的__init__方法。在创建实例的时候,绑定相关的属性。比如前面的name,score.

class Student:
    school = 'zucc'、、
    def  __init__ (self,name,score):
        self.name = name
        self.score = score
stu1 = Student('tom',99)  #实例化
print((stu1.name,stu1.score,stu1.school))

和普通函数相比,在类定义方法时,第一个参数必须是self。除都哟个参数外,其他的和普通函数没什么区别。

self 代表的是实例,而非类

class Student:
    def test_instance(self):
        print(self)
test = Student()
test.test_instance()
#<__main__.Student object at 0x000001D872709390>

__init__方法

  • 为对象初始化自己独有的特征
  • 该方法中可以有任意的代码,但是一定不可以有返回值。

3.1 数据封装

class student:
    def __init__(self, name , score):
            self.name = name
            self.score = score

    def find_score(self):
        print(self.name,':',self.score)
stu1= student('tom',99) #实例化的过程
stu1.find_score()

我们通过__init__()让stu1 实例本身拥有了相关数据,如果要访问这些数据,我们可以直接在student类内部定义相关的函数来访问数据,以此‘封装’数据。

这些封装数据的函数和student类本身是关联起来的,他们被称之为方法。

class Point:
    pass
p1 =Point()
p2 =Point()
p1.x=5
p1.y=4

p2.x=3
p2.y=6
print(p1.x,p1.y)
print(p2.x,p2.y)
#5 4
#3 6
#通过点记法给一个实例化的对应赋予任何属性。没有任何行为

class Point:
    def reset(self,x,y):
        self.x=x
        self.y=y
p = Point()
p.reset(4,5)
print(p.x,p.y)
#4 5
import math
class Point:
    def __init__(self,x,y):
        # self.x=x
        # self.y=y
        self.move(x,y)
    def move(self,x,y):
        self.x=x
        self.y=y
    def reset(self):
        self.move(0,0)
    def cal_distance(self,other_point):
        return math.sqrt(
            (self.x-other_point.x)**2 +
            (self.y-other_point.y)**2)

# p1=Point()
# p2=Point()
# p3=Point()
#
# p1.reset()
# p2.move(3,4)
# p3.move(6,8)
# print(p2.cal_distance(p1))
# print(p2.cal_distance(p3))
p = Point(3,4)
print(p.x,p.y)
#3 4 

类的作用:

  • 属性引用

    • 类名·属性
  • 实例化

    • 类名加速一个括号就是实例化,他能够自动触发__init__函数的运行,进而为每个实例定制自己的特征。
  • 类属性的补充

    • 1.dir(类名)
    • 返回一个列表
    • 2.类名._dict_
    • 返回一个字典,key属性名,value为属性值
class student:
    school='zucc'
    def __init__(self, name , score):
            self.name = name
            self.score = score

    def find_score(self):
        print(self.name,':',self.score)
stu1= student('tom',99) #实例化的过程
stu1.find_score()
print(dir(student))
#多了school
  • 特殊的类属性
类名.__name__#返回类的名字
类名.__doc__#返回文档字符串
类名.__base__#类的第一个父类
类名.__bases__#类的所有父类构成的元组
类名.__module__#类定义所在的模块
类名.__class__#实例所对应的类
类名.__dict__#类的字典属性

总结:

class ClassName:
  def __init__(self,para1,para2,para3,para4..):
    self.对象属性1 =para1
    self.对象属性2 =para2
    
  def 方法名1(self):
      pass
  def 方法名2(self):
      pass
obj=ClassName(para1,para2)
#对象的实例化,代表具体的东西
#ClassName():调用__init__
#括号内传参,无序传入self,参数一一对应
#结果返回对象obj
obj.对象属性1#查看对象属性
obj.方法名1#调用类的方法
  • 对象直接的交互

    假如说现在定义两个类,person,dog

class Person:
    def __init__(self, name, aggressivity, life_value):
        self.name = name
        self.aggressivity = aggressivity
        self.life_value = life_value
    def attack(self,dog):
        dog.life_value -=self.aggressivity
class dog:
    def __init__(self,name,breed,aggressivity,life_value):
        self.name = name
        self.breed = breed
        self.aggressivity = aggressivity
        self.life_value = life_value
    def bite(self,people):
        people.life_value -=self.aggressivity

per = Person('jack', 10, 1000)
dog1 = dog('jerry', 'husky', 8, 1000)
per.attack(dog1)
print(dog1.life_value)
  • 类命名空间与对象,实例空间

创建一个类就会创建一个类的名称空间,用来存储我们定义的所有的变量名。这些名字就是属性。

类的属性有两种:

  • 静态属性(共享给所有对象的)
    • 直接在类中定义的变量
  • 动态属性(绑定给某一个对象的)
    • 在类中定义的方法
class student:
    school='zucc'
    def __init__(self, name , score):
            self.name = name
            self.score = score

    def find_score(self):
        print(self.name,':',self.score)
stu1= student('tom',99)
stu2=student('jack',82)
print(id(stu1.school))
print(id(stu2.school))
print(stu1.find_score)
print(stu2.find_score)
print(student.find_score)
#2356733121176
#2356733121176
<bound method student.find_score of <__main__.student object at 0x00000224B83D9D68>>
<bound method student.find_score of <__main__.student object at 0x00000224B83D9E10>>
#<function student.find_score at 0x00000224B8590620>

4.0 函数的三大特性

  • 继承
  • 多态
  • 封装

4.1继承

在面向对象编程中,当我们定义一个新的类的时候,可以从某个现有的类继承,新的类就被称为子类(Subclass),而被继承的类则被称为基类,父类,超类(Base Class,Father Class,Super Class)

比如,我们定义一个动物类(Animal),其有一个run()方法如下:

class Animal(object):
    def run(self):
        print('Animal is runing')
class dog(Animal):
    pass
class cat(Animal):
    pass
dog = dog()
cat = cat()
print(dog.run())

4.1.1继承的查看

class Animal(object):
    def run(self):
        print('Animal is runing')
class Animal2:
    pass
class Dog(Animal):
    pass
class Cat(Animal):
    pass
class Husky(Animal,Animal2): #多继承,逗号分开
    pass

dog = Dog()
cat = Cat()
print(Dog.__bases__)
print(Husky.__bases__)
print(Animal.__bases__)
#如果不指定基类,python类会默认继承object类
#object是所有python类的基类 ,提供一下常见方法的实现
#(<class '__main__.Animal'>,)
#(<class '__main__.Animal'>, <class '__main__.Animal2'>)
#(<class 'object'>,)

4…1.2 多态

当子类和父类存在相同的方法时,子类的方法会覆盖父类的方法,再运行代码时,总会调用子类的方法。这样就是继承的另一个好处,多态。

class Animal(object):#定义父类
    def run(self):
        print('Animal is runing')
class Animal2:
    pass
class Dog(Animal):
    def run(self):
        print('Dog is running')
class Cat(Animal):
    def run(self):
        print('Cat is running')
class Husky(Animal,Animal2): #多继承,逗号分开
    pass

dog = Dog()
cat = Cat()
print(dog.run())
print(cat.run())
#Dog is running
#Cat is running

理解多态,首先要对数据类型再进行说明。定义一个类的时候实际上就是定义了一种数据类型。我们自定义的数据类型和python自带的数据类型,比如str,list,dict,没什么区别。我们可以用isinstance()来判断某个变量是否是某个类型

对于一个变量,我们只有知道他的父类型,无需确切知道子类型,就可以放心调用相关的方法。运行时具体的方法时作用在子类型上还是父类型上,由我们运行的对象决定。

也就是说,调用时只管调用,不管细节。

当我们新增一个子类时,只要保证相关的方法编写正确,就不用管原来的代码是如何调用的。

—>‘开闭’原则

  • 对拓展开放:允许新增子类
  • 对修改封闭:不需要修改依赖父类类型的函数

总结:

继承可以一级一级的继承下来,类比人类,就好比,爷爷奶奶到父母,再到子女

任何类都可以追溯到根类object。

4.1.3私有属性

在类的内部,可以有属性和方法,而外部代码可以通过总结调用实例变量的方法来操作。这样,隐藏内部的复杂逻辑。

比如student类

class student:
    school='zucc'
    def __init__(self, name , score):
            self.name = name
            self.score = score

    def find_score(self):
        print(self.name,':',self.score)
stu1= student('tom',99) #实例化的过程
stu1.find_score()
print(stu1.score)
stu1.score=90
print(stu1.score)

从这里可以看出,外部代码可以自由修改一个实例的属性(name,score)

如果要让内部属性不被外部访问,我们可以在属性的名称前,加上双下划线。并写一个函数调用属性名称def return

在python中,实例的变量名如果以双划线开头,就变成了一个私有变量,只有内部可以访问。所以我们改一下student类

class Student:
    school='zucc'
    def __init__(self, name , score):
            self.__name = name
            self.__score = score

    def get_name(self):
        return self.__name

    def ger_score(self):
        return self.__score

    def set_score(self,score):
        if 0<=score<=100:
            self.__score = score
        else:
            raise ValueError('bad score')

    def find_score(self):
        print(self.__name,':',self.__score)
stu1= Student('tom',99)
# 实例化的过程
stu1.find_score()
print(stu1.ger_score())
stu1.score = 90
print(stu1.ger_score())
print(stu1.set_score(5))
print(stu1.find_score())
print(stu1._Student__score)
# 可以单下划线加类访问 不建议

4.1.4 封装

隐藏对象的属性和时间细节,仅对外提供公共访问的方式。

这样的优点在于:

  • 可以将变化隔离
  • 便于使用
  • 提高数据的安全性
  • 提高复用性

封装的原则是:

  • 将不需要对外提供的内容隐藏起来
  • 隐藏属性,提供公共方法对其进行访问

—>私有方法,私有变量—>私有属性

用双下划线开头的方式将属性隐藏,设置为私有的。

5.0 面向对象2

5.1 静态方法

  • 通过装饰器@staticmethod 来进行装饰。静态方法既不需要传递对象也不需要传递实例对象
  • 静态方法也可以通过我们实例对象类对象的访问。
class Dog:
    type='狗'
    def __init__(self):
        name =None
    #静态方法
    @staticmethod
    def introduce(): # 静态方法不会自动传递实例对象和类对象
        print('犬科哺乳动物,属于肉食目')
dog = Dog()
Dog.introduce()
dog.introduce()
#犬科哺乳动物,属于肉食目
#犬科哺乳动物,属于肉食目

静态方法时类中的函数,不需要实例。

静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但和类本身没有关系,也就是说,在静态方法中,不会涉及类的属性和方法的操作。

—>可以理解为静态方法是一个独立的,单纯的函数,仅仅是托管与某个类的名称空间中,便于维护和管理。

5.2类方法

  • 类对象所拥有的方法
  • 需要用装饰器@classmethmod来标识其为类方法。
  • 对于类方法,第一个对象必须是类函数,一般以 cls 作为第一个参数。
class Dog:
    __type = '狗'
    # 类方法,用class来进行装饰
    @classmethod
    def get_type(cls):
        return cls.__type
print(Dog.get_type())
#狗

使用场景:

  • 当方法中需要使用类对象(如访问私有类属性等)时,定义类方法。
  • 类方法一般和类属性配合使用。

注意:

类中定义了同名的对象方法,类方法以及静态方法时,调用方法会优先访问最后一个

class Dog:
    def demo_method(self):
        print('对象方法。')

    @classmethod
    def demo_method(cls):
        print('类方法')
    @staticmethod
    def demo_method(): # 最后被定义,调用时优先执行
        print('静态方法')
dog = Dog()
Dog.demo_method()
dog.demo_method()
#静态方法
#静态方法

property

概述

在python中主要为属性提供一个便利的操作方式。

如果我们现在需要设计一个银行账户类,类中包含账户人的姓名,余额。(假如现在不考虑具体的操作接口)

简单的实现

class Account(object):
    def __init__(self,name,money):
        self.name = name
        self.money = money

问题:

不安全(设计很简单方便,所有属性,外部都可以访问修改,非常不安全)

改进1:隐藏现实细节

对账户信息而言,金额不允许让用户之间修改。如果修改,只能去窗口办理。

程序如何实现?

在使用对象时,尽量不要让使用者之间操作对象中的属性,因为之间操作会带来安全隐患。

这个时候,考虑私有属性

class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__money = money

代码改进后,将所有的属性设计成私有属性后。确实从外部使用时,不知道内部的属性,不能直接修改对象,隐藏了实现的细节。

但一个新的问题,如果确实需要对这两个属性进行修改 ,怎么办?

改进2:提供一个精确的访问

添加访问,访问私有属性。

class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__balance = money
    def get_name(self):
        return self.__name
    def set_balance(self,money):
        self.__balance = money
    def get_balance(self):
        return self.__balance

经过修改,外部使用这个类的对象时,想使用对象中的属性,只能通过类中提供的 set/get 接口来操作,提高了程序的安全性。

这样,程序基本达到了设计需求,但是能不能更加完善呢?

如果在使用这个类的对象过程中,由于误操作,传入了不正常的数据,导致数据异常。该如何以避免这种情况发生呢?

比如:设置金额时出现了负数,或字符串,或其它类型的对象。

改进3:保证数据有效性

set_balance 方法中,对传入数据进行有效性判断,

class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__balance = money
    def get_name(self):
        return self.__name
    def set_balance(self,money):
        if isinstance(money,int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('金额不正确')
        else:
            raise ValueError('输入金额不是数字')
        self.__balance = money
    def get_balance(self):
        return self.__balance

经过几个版本的迭代,程序看上去越来越健壮,安全性能也越来越高。

但是在使用过程中,可不可以更精炼一些?

属性操作。

property 类

在python中,提供了一个property类,通过对创建这个类的对象的设置,在使用对象的私有属性时,可以不再使用属性的函数调用方式,而是像普通的共有属性一样去使用属性,为开发者提供便利。

property(fget=None,fset=None,fdel=None,doc=None) #--->property attribute

property 是一个类,__init__方法由四个参数组成,实例后返回一个用来操作的对象

参数一:属性的获取方法

参数二:属性的设置方法

参数三:属性的删除方法

参数四:属性描述

使用property

class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__balance = money
    def __get_name(self):
        return self.__name
    def set_balance(self,money):
        if isinstance(money,int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('金额不正确')
        else:
            raise ValueError('输入金额不是数字')
        self.__balance = money
    def get_balance(self):
        return self.__balance
name  = property(__get_name)
balance = property(get_balance,set_balance)

ac=Account('TOM',10000)
print(ac.name)
print(ac.balance)
class Account(object):
    def __init__(self,name,money):
        self.__name = name
        self.__balance = money
    @property
    def name(self):
        return self.__name
    @property
    def balance(self):
        return self.__balance
    @balance.setter
    def balance(self,money):
        if isinstance(money,int):
            if money > 0:
                self.__balance = money
            else:
                raise ValueError('金额不正确')
        else:
            raise ValueError('输入金额不是数字')
        self.__balance = money
    def get_balance(self):
        return self.__balance


ac=Account('TOM',1000)
print(ac.name)
print(ac.balance)
ac.balance= 10
print(ac.balance)
#TON
#1000
#10

self

如果对象的方法中,需要使用该对象的属性,该怎么办?

  • 关键字self主要用于对象方法中,表示调用该方法的对象。
  • 在方法中使用self,就可以获取到调用当前方法的对象,进而获取到该对象的属性和方法。

调用对象的方法时,为什么不需要设置self对应的参数?

  • 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给方法,所以开发者只需要在 定义的时候预留第一个参数self即可。
class Cat:
    def introduce(self):
        print('name is %s ,age is %d' %(self.name,self.age))
# 实例化 创建一个对象
cat =Cat()
cat.name='123'
cat.age=5
cat.introduce()
#name is 123 ,age is 5

方法内定义属性

  • 使用self操作属性和对象的变量名在效果上类似。如果属性在赋值时还没有被定义。就会自动定义一个属性并赋值。
class Cat:
    def introduce(self):
        self.type = '小型动物'


cat = Cat()
cat.introduce()
print(cat.type)

__new__方法

  • 创建对象时,系统会自动调用__new__方法。

  • 开发者可以使用__new__方法来自定义对象的创建过程。

  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供。

  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例。

  • __init__有一个参数self,就是这个__new__返回的实例,__init____new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值。

  • 如果创建对象时传递了自定义参数,且重写了__new__方法,则__new__也必须 “预留” 该形参,否则init方法将无法获取到该参数。


__call_方法

对象后面加括号,触发执行

构造方法和执行是由创建对象触发的,即:对象=类名()

而对于,__call_方法的执行是由对象加括号触发的,即对象()或者类()

class A(object):
    def __init__(self):
        pass
    def __call__(self, x):
        print('__call__called,print x :',x)
a=A()
a('123')
#__call__called,print x : 123

isinstance 和 issubclass(判断是否为子类)

isintance(obj,cls)检查obj是否是cls的对象

class Foo:
    pass
foo =Foo()
print(isinstance(foo,Foo))
print(isinstance(1,int))
#True
class Foo():
    pass
class Bar(Foo):
    pass
print(issubclass(Bar,Foo))
#True

反射

所谓反射,是指程序可以访问,检测和修改它本身状态或者行为的一种能力(自省)

在python中,面向对象中的反射是指通过字符串的形式操作对象的相关属性。

四个可以实现自省的函数

  • hasattr(检测是否含有某个属性)

  • hasattr(*args,**kwargs)

    class Foo:
        f = '类的静态变量'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def say(self):
            print('hello,%s' % self.name)
    
    
    obj = Foo('tom', 22)
    # 检测是否含有某个属性
    print(hasattr(obj,'name'))
    print(hasattr(obj,'say'))
    #True
    #True
    
  • getattr(获取属性)

  • getattr(obj,name,defult=None)

    gt = getattr(obj,'name')
    print(gt)
    gtf =getattr(obj,'say')
    gtf()
    gtf1 = getattr(obj, 'hello')  # 不存在报错
    # True
    # hello,tom
    
  • setattr(设置属性)

setattr(obj, 'good man', True)
setattr(obj, 'show_name', lambda self: self.name + 'good man')
print(obj.__dict__)
print(obj.show_name(obj))
#{'name': 'tom', 'age': 22, 'good man': True, 'show_name': <function <lambda> at 0x0000027F35DCAA60>}
#tomgood man
  • delattr(删除属性)

    delattr(obj, 'show_name')
    print(obj.__dict__)
    delattr(obj, 'sss')  # 报错
    #{'name': 'tom', 'age': 22, 'good man': True}
    

联想,字符串,列表,元组可以通过索引值引用值,字典可以通过关键字引用值,用了[ ]。

item系列

class Foo:

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

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, item):
        print('del obj[key]时:')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj.key时:')
        self.__dict__.pop(item)


obj1 = Foo('Tom')
obj1['age'] = 18
obj1['age1'] = 19
print(obj1.__dict__)
del obj1['age']
del obj1.age1
#{'name': 'Tom', 'age': 18, 'age1': 19}
#del obj[key]时:
#del obj.key时:
#{'name': 'Tom'}
#{'name': 'jack'

__del__

析构方法,当对象在内存中被释放,就会自动触发执行。

一般不需要自定义。

class Foo:
    def __del__(self):
        print('执行DEL函数了')
obj = Foo()
del obj

__str__

  • 如果直接print打印对象。就会看见创建对象的内存地址。

  • 当我们使用print(xxx),输出对象,如果对象中定义了__str__方法,就会打印该方法return的信息描述

class Cat:
    def __init__(self, new_name, new_age):
        self.name = new_name
        self.age = new_age

    def __str__(self):  # 没有这个语句print输出的是地址
        return '名字是:%s,年龄是:%s' % (self.name, self.age)


obj = Cat('Tom', 3)
print(obj)
#名字是:Tom,年龄是:3
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值