day32 各种魔法方法

在这里插入图片描述

__init__ 在 类名() 触发它的执行

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print('执行....')
        
        
p = Person('xio', 18)  # 执行....

__setattr__ :在 对象.属性=值 会触发它的执行

class Person:
    def __setattr__(self, key, value):
        print('我执行了')
        print(key)
        print(value)

        # self.key=value  # 根本不对
        # setattr(self,key,value)  # 本质会调用对象自己的__setattr__ ,出递归,报错
        object.__setattr__(self, key, value)  # 把key,value放到了object里


p = Person()
p.name = 'xio'
'''
我执行了
name
xio
'''

__getattr__ :在 对象.属性 获取值会触发它的执行

class Person:
    def __getattr__(self, item):  # 当属性不在对象中,会触发它的执行
        print('我执行了')
        
        
p = Person()
print(p.age)
'''
我执行了
None
'''
# 如果类里面有age属性那就不会触发__getattr__,而直接打印age的值

__delattr__ :在 del 对象.属性 会触发它的执行

class Person:
    def __delattr__(self, item):
        print('删除会触发我')
        
        
p = Person()
del p.name  # 删除会触发我
# 不管属性存不存在 都会del都会触发__delattr__运行

多态性的使用

ll = [1, 2, 3]
dic = {'name': 'lqz', 'age': 19}
print(len(ll))  # 面向对象多态性的使用
print(len(dic))  # 面向对象多态性的使用
# # len内部调用了ll.__len__()
# # len内部调用了dic.__len__()


# setattr(对象,key,value)
# 内部:对象.__setattr__(key,value)
# 保证对象必须要有__setattr__,所有类的基类,object中有__setattr__


dix = {'name': 'xio'}
print(dix['name'])  # xio
print(dix.name)  # 报错

__getattribute__无论属性在对象中是否存在,都先触发__getattribute__的执行

### 无论属性在对象中是否存在,都先触发__getattribute__的执行(用的比较少)
class Person:
    name = 'xio'

    # 属性不存在,才触发
    def __getattr__(self, item):
        print('getattr触发了')

    def __getattribute__(self, item):
        print('__getattribute__触发了')


p = Person()
print(p.name)
'''
__getattribute__触发了
None
'''

# 对象.属性 调用顺序   先执行:__getattribute__----》类的名称空间----》__getattr__(本质是去对象自己的名称空间拿东西)
# 对象.属性的查找顺序

#当getattribute与getattr同时存在,只会执行getattrbute,除非getattribute在执行过程中抛出异常AttributeError

__setitem____getitem____delitem__

# __getitem__: 通过中括号取值触发它的执行
# __setitem__:通过中括号赋值,触发它的执行
# __delitem__:通过中括号删除值,触发它的执行

class Person:
    def __getitem__(self, item):
        print('__getitem__执行')

    def __setitem__(self, key, value):
        print('__setitem__执行')

    def __delitem__(self, key):
        print('__delitem__执行')


p = Person()
p['name'] = 'lqz'  # __setitem__执行
p['name']  # __getitem__执行
del p['age']  # __delitem__执行


__format__ 调用format(对象,‘字符串格式’)触发

# 一 字符串格式
s = '我的名字是:%s' % 'xio'
print(s)  # 我的名字是:xio

# 字符串的format方法支持的格式化方式

res = '我的名字是{},年龄是{}'.format('xio', 18)
res1 = '我的名字是{0},年龄是{1}'.format('xio', 18)

ll = ['xio', 19]
l2 = ['男']
res = '我的名字是{0[0]},年龄是{0[1]},性别是{1[0]}'.format(ll, l2)
dic = {'name': 'xio', 'age': 19, 'sex': '男'}
res1 = '我的名字是{name},年龄是{age},性别是{sex}'.format(**dic)

class Person:
    def __init__(self):
        self.name = 'xio'
        self.age = 19
        self.sex = '男'


p = Person()
# res='我的名字是{0.name},年龄是{0.age},性别是{0.sex}'.format(p)
res = '我的名字是{obj.name},年龄是{obj.age},性别是{obj.sex}'.format(obj=p)
print(res)  # 我的名字是xio,年龄是19,性别是男
  • 对象的__format__ 调用format(对象,‘字符串格式’)触发
class Person():
    __dic = {
        'n-a': '名字是:{obj.name}-----年龄是:{obj.age}',
        'n:a': '名字是:{obj.name}:::::年龄是:{obj.age}',
        'n/a': '名字是:{obj.name}/年龄是:{obj.age}',
    }

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

    def __format__(self, format_spec):
        # print(format_spec)
        if format_spec and format_spec in self.__dic:
            s = self.__dic[format_spec]
        else:
            s = self.__dic['n-a']
        return s.format(obj=self)


p = Person('xio', 18, '男')

res = format(p)  # 名字是:xio-----年龄是:18
res = format(p, 'n-a')  # 名字是:xio-----年龄是:18
res = format(p, 'n/a')  # 名字是:xio/年龄是:18
res = format(p, 'n:a')  # 名字是:xio:::::年龄是:18
print(res)


__del__ 调用del功能时触发

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __del__(self):
        # 资源清理工作
        print('xxxx')


p = Person('xio',18)
del p
# xxxx
class ProcessFile:
    def __init__(self,name):
        self.f=open(name,'wt',encoding='utf-8')

    def write(self,s):
        self.f.write(s)

    def close(self):
        self.f.close()

    def __del__(self):
        # 请理性的工作
        self.f.close()

p=ProcessFile('a.txt')
p.write('xxxx')
p.close()

# del p  系统结束后会自动运行,然后触发__del__方法

__doc__查看类的注释信息

class Person:
    '''
    类的提示信息,注释
    '''
    pass


print(Person.__doc__)  # 类的提示信息,注释
# 查看不了父类的

__call__ 对象() 触发执行

# 不支持对象()调用
class Person:
    def __init__(self, name):
        self.name = name


p = Person('xio')
p()
# 支持
class Person:
    def __init__(self, name):
        self.name = name

    def __call__(self, *args, **kwargs):
        print('我执行了')


p = Person('xio')
p()  # 触发__call__的执行,里面有什么,就会执行什么
# 1 后期flask源码中使用了它

# from flask import Flask
# print(Flask.__doc__)
# # 类实例化得到一个对象
# # 当有一个请求过来,内部会执行 app()
# # Flask类的 __call__是整个flask项目的入口
# app=Flask(__name__)

# 2 一切皆对象
# Person 类,也是一个对象   Person()----->触发生成Person类的类的__call__,不是触发Person的__call__
# Person类生成的对象 --->p()--->触发Person的__call__

__init____new__

# __init__  对象初始化调用   类() 会触发
# __new__   对象生成        类() 会触发,是在__init__之前触发

class Person:
    def __init__(self, name):
        print('我执行了,我是__init__')
        self.name = name

    def __new__(cls, *args, **kwargs):
        print('我出生了')
        # __new__内部会触发 self.__init__的执行
        obj = object.__new__(cls)
        # return {'name':'l1z'}  # 不会触发__init__
        return obj  # 触发 __init__


p = Person('xio')  # 触发__new__,返回 obj 对象

print(p)
'''
我出生了
我执行了,我是__init__
<__main__.Person object at 0x7f8f22789f10>
'''
'''
Person()---->本质触发的是__new__,因为__new__返回什么对象就是什么
__init__是初始化方法,在__new__后执行的

__new__:创造出一个空对象,没有初始化
__init__:创造完空对象后,再触发它,完成初始化

'''
# 总结:类实例化得到对象,本质是在执行类的 __new__,返回什么对象,p拿到的就是什么对象,在__new__内部,调用了__init__
# 如果__new__没有返回值,print(p)返回的就是None

__module____class__

# __class__   对象.__class__   查看对象的类

class Animal:
    pass


class Person(Animal):
    pass


print(Person.__bases__)  # (<class '__main__.Animal'>,)  # 查看父类 
p = Person()

print(p.__class__)  # <class '__main__.Person'>
# __modules__:看对象属于哪个模块(用的很少,了解即可)


from a import C

obj = C()


class Person():
    pass


p = Person()
print(obj.__module__)  # a
print(p.__module__)  # __main__

__str____repr__

# __str__ : print(对象) 触发对象的 __str__,优先触发 __str__
# __repr__: 再命令窗口中直接写 p 触发 __repr__


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

    def __str__(self):  # 会经常写
        return self.name + 'ddddd'

    def __repr__(self):  # 写的少
        return self.name


p = Person('xio')
print(p)

__slots____dict__

# __slots__:控制对象可以使用的属性
# __dict__: 对象属性

# slots是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
# 使用点来访问属性本质就是在访问类或者对象的dict属性字典(类的字典是共享的,而每个实例的是独立的)

#  一旦使用了slots,对象就没有自己的dict了
#  slots的实际应用场景
# 1 限制对象的属性
# 2 节省内存(对象很多,但属性很少,使用它,节省内存)

# 一个类,每生成一个对象,对象有自己的dict,如果对象自身有很多属性,(对象越多)这样占用的内存空间就很多
# 使用了slots后,所有的对象,都使用类名称空间中的属性,对象越多,越节省内存


# 字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用slots取代实例的dict


class Person:
    __slots__ = ['name', 'age']  # 对象只拥有name和age属性,没有xxx属性

    def __init__(self, name, age, xxx):
        self.name = name
        self.age = age
        # self.xxx = xxx

    def __str__(self):
        return self.name


p1 = Person('xio', 19, 'xxx')
p2 = Person('json', 18, 'xxx')

# 对象自己没有名称空间了,统一全用类的名称空间
# print(p1.__dict__)  # AttributeError: 'Person' object has no attribute '__dict__'
# print(p2.__dict__)  # AttributeError: 'Person' object has no attribute '__dict__'
# print(p1.__slots__)  # ['name', 'age']
# print(p2.__slots__)  # ['name', 'age']
print(p1.name)  # xio  # 调用的是类里面的属性
print(p1.age)  # 19  # 调用的是类里面的属性

print(Person.__dict__)
# {'__module__': '__main__', '__slots__': ['name', 'age'], '__init__': <function Person.__init__ at 0x7fe5eaac1a60>, '__str__': <function Person.__str__ at 0x7fe5ead864c0>, 'age': <member 'age' of 'Person' objects>, 'name': <member 'name' of 'Person' objects>, '__doc__': None}



# 总结
'''
## slots的实际应用场景
# 1 限制对象的属性
# 2 节省内存(对象很多,但属性很少,使用它,节省内存)

'''

__all__ 导入模块时可以限制使用的属性

# __all__:使用from  a import  *导入模块时,限制能够使用的属性
# __all__=['age','name']

'''a.py
__all__ = ['age', 'name']
age = 10
name = 'xio'
sex = '男'
'''

from a import *

print(age)  # 10
print(name)  # xio
print(sex)  # NameError: name 'sex' is not defined # 调不到

__iter____next__

	-可迭代对象:对象有__iter__方法,这个对象就是一个可迭代对象
    	-for循环本质就是在循环可迭代对象
        -for i in 对象(必须是可迭代对象)
        -for循环的本质:先调用对象的__iter__得到一个迭代器对象,然后调用迭代器		
         对象的__next__ 方法,每次获得一个值(next这种获取值的方式不依赖于索引,又叫迭代循环)
    -迭代器对象:
    	-既有__iter__又有__next__的对象,就是迭代器对象
        -迭代器对象一定是可迭代对象
    -定制自己的可迭代对象
    	-重写类中的__iter__和__next__
        -让它支持for循环直接循环(做出一种不依赖于索引取值的方式)
        -不停的return 值,当要停下时,抛出异常
# 0 链式调用(跟语言无关)
# f.test().test2().test3()  # java,js:中广泛应用,设计程序的模式

# 如何实现支持链式调用的对象
class Foo:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def print_name(self):
        print(self.name)
        return self

    def print_age(self):
        print(self.age)
        return self

    def print_sex(self):
        print(self.sex)
        return self


f = Foo('xio', 16, '男')
f.print_name()
f.print_sex()
f.print_age()

# 链式调用
f.print_name().print_sex().print_age()  # 每次用.调用完得到的都是return的返回值
  • __iter____next__ 的应用
# 1 给一个类,重写__iter__,__next__
class Foo:
    def __init__(self):
        self.__x = 1

    def __iter__(self):
        return self

    def __next__(self):
        self.__x += 1
        return self.__x


f = Foo()  # f就是一个可迭代对象,所以他就能够被for 循环

for i in f:  # f.__iter__()----->每循环一次,调用一下 f.__next__()
    print(i)
# 自定制可迭代对象(自己写的对象,可以迭代,可以被for循环)
# 加入异常,for循环该对象,可以停止

# 实现自己的range
class MyRange:
    def __init__(self, start, end, step=1):
        self.__start = start
        self.__end = end
        self.__step = step

    def __iter__(self):
        return self

    def __next__(self):
        self.__start += self.__step
        if self.__start >= self.__end:
            raise StopIteration('')  # 抛出一个异常,程序就结束了
        return self.__start


for i in MyRange(1, 20):
    print(i)
  • 练习题:斐波那契数列(通过__iter__和__next__实现)
class Fib:
    def __init__(self, count):
        self.start = 0
        self.second = 1
        self.count = count

    def __iter__(self):
        return self

    def __next__(self):
        self.start, self.second = self.second, self.start + self.second
        if self.start >= self.count:
            raise StopIteration()
        return self.start


for i in Fib(100):
    print(i)

__len__

# __len__:计算对象长度,返回几,len(对象),结果就是几


class Foo:

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

    def __len__(self):
        # return len(self.__dict__)
        return 5


f = Foo('xio', 19)
f.hobby = 'xxx'

print(len(f))  # 5 

__hash__

# __hash__   ,hash(对象)触发执行,返回什么就是什么
# 如果一个对象不可hash,通过重写 __hash__让它变得可hash

# 可变类型,不可hash
# 不可变类型,可以hash

# l = ['1', 3, 54, 56]
# dic = {'name': 'lqz'}
#
# a = 10
#
# print(hash(a))
# # print(hash(dic))
# print(hash(l))

#
class Foo:
    def __init__(self):
        self.name = 'lqz'
        self.l = ['1', 3, 4]

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


f = Foo()
print(hash(f))

__eq__

# 两个对象 == 比较的时候,触发 __eq__的执行,在内部,自定制比较规则即可

# a=10
#
# b=100
# print(a==b)
#
# l=[1,3,4]
# l2=[1,3,4]
# print(l==l2)
#
# print(a==l2)  # 注意,可以通过 == 比较


class Foo:
    def __str__(self):
        return self.name

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

    def __eq__(self, other):
        print(self)  # xio
        print(other)  # json
        # 自己定制比较规则
        if self.name == other.name:
            return True
        else:
            return False


f1 = Foo('xio')
f1.age = 999

f2 = Foo('json')
f2.age = 888
print(f1 == f2)  # False
print(f1 is f2)  # 不会触发__eq__

__enter____exit__ 上下文管理器

# with open() as f:
# with 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明enter和exit方法
'''a.txt
hello word
'''

# 自定制一个open,打开文件
class Open:
    def __init__(self, path, mod='rt', encoding='utf-8'):
        self.f = open(path, mod, encoding=encoding)

    def __enter__(self):
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):  # with结束后运行
        # 如果exc_tpye 不为空,表示with上下文内部出了错误,处理错误
        if exc_type:
            print('程序出错了,但是我处理好了,继续执行就好了')
            print(exc_val)
            return True
        # 没有错误,正常结束,资源清理工作(关闭文件)
        print('文件关闭了,放心好了')
        self.f.close()
    # def read(self):
    #     return self.f.read()


# 后期会使用with ,处理数据库链接,redis链接

with Open('a.txt', 'r', encoding='utf-8') as f:
    res = f.read()  # res的值是__enter__ return出来的
    print(res)  # hello word

'''
优点:
使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在exit中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处
'''

描述符

__get__(),__set__(),__delete__() 的应用

class Str():
    def __get__(self, instance, owner):
        print(self)  # <__main__.Str object at 0x00000220483C4670>  # Str的对象
        print(instance)  # <__main__.People object at 0x00000220483C4C40>  # People的对象
        print(owner)  # <class '__main__.People'>  # People这个类

    def __set__(self, instance, value):
        print(self)  # <__main__.Str object at 0x00000220483C4670>  # Str的对象
        print(instance)  # <__main__.People object at 0x00000220483C4C40>  # People的对象
        print(value)  # xio

    def __delete__(self, instance):
        print(self)  # <__main__.Str object at 0x00000220483C4670>  # Str的对象
        print(instance)  # <__main__.People object at 0x00000220483C4C40>  # People的对象


class People:
    name = Str()
    # 只要类属性被描述符类代理了,以后使用   对象.属性   ,就会触发描述符类的__set__,__get__,__delete__,
    # 并且只在类名称空间有,对象名称空间就没有该属性了

    def __init__(self):  # name被Str类代理
        self.name = 'xio'  # 赋值,就会触发描述符类的__set__方法


p = People()  # 触发__init__---> 触发self.name = 'xio'---> 触发__set__
p.name  # 触发name = Str()---> 触发__get__
del p.name  # 触发name = Str()---> 触发__delete__

描述符的种类

  • 数据描述符:至少有__get____set__
class Str:
    def __get__(self, instance, owner):
        pass

    def __set__(self, instance, value):
        pass

    def __delete__(self, instance):
        pass
  • 非数据描述符:没有实现__set__
class Str1:
    def __get__(self, instance, owner):
        pass

    def __delete__(self, instance):
        pass

对象.属性:取值的顺序

# 描述符本身应该定义成新式类,被代理的类也应该是新式类
# 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
# 要严格遵循该优先级,优先级由高到底分别是
# 1.类属性
# 2.数据描述符
# 3.实例属性    (对象属性)
# 4.非数据描述符
# 5.找不到的属性触发getattr()

赋值类型限制

# python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能

class Typed:
    def __init__(self, name, type_key):
        self.name = name
        self.type_key = type_key

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if isinstance(value, self.type_key):
            instance.__dict__[self.name] = value  # 放到对象中去了
        else:
            print('类型不合法,不能放')

    def __delete__(self, instance):
        print(instance)
        print(f'已删除 {instance.__dict__}')


class People:
    name = Typed('name', str)
    age = Typed('age', int)
    salary = Typed('salary', float)
    is_marrey = Typed('is_marrey', bool)


p = People()
p.name = 'xio'  # 触发name = Typed('name', str)---> 触发__set__把name='xio'保存到People对象p里
print(p.name)  # 触发name = Typed('name', str)---> 触发__get__把People对象p里的name取出来
del p.name  # 触发name = Typed('name', str)---> 触发__delete__把People对象p.__dict__里的{'name': 'xio'}删除

print(People.__dict__)
'''
{'__module__': '__main__', 'name': <__main__.Typed object at 0x00000161086A4670>, 'age': <__main__.Typed object at 0x00000161086E9340>, 'salary': <__main__.Typed object at 0x00000161086E93D0>, 'is_marrey': <__main__.Typed object at 0x00000161086E9370>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
'''
# name、age、都对应的是Typed的实例对象

复制类型限制 装饰器

class Typed:
    def __init__(self, name, type_key):
        self.name = name
        self.type_key = type_key

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if isinstance(value, self.type_key):
            instance.__dict__[self.name] = value  # 放到对象中去了
        else:
            print('类型不合法,不能放')

    def __delete__(self, instance):
        print(instance)
        print('delete')


def typeassert(**kwargs):
    def decorate(cls):
        # print('类的装饰器开始运行啦------>', kwargs)
        for key, value in kwargs.items():
            # print(key)
            # print(value)
            # cls.__dict__[key]=value  # 类的__dict__不支持修改,只能取值,作者做的
            # setattr(cls,key,value)  # 通过反射
            setattr(cls, key, Typed(key, value))  # Typed(key, value)调用描述符做类型的判断
            # 把key和value存到类中
        return cls

    return decorate


@typeassert(name=str, age=int, salary=bool)
class People:
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.salary = salary


@typeassert(name=str, age=int)
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age


a = Animal('xio', 18)
p = People('xio', 18, True)  # decorate(People)()

# print(People.__dict__)

自己定制一个property装饰器

class Lazyproperty:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        # self.func是 Room类的area的内存地址,普通函数---需要传对象  area(instance)
        print('我被执行')
        return self.func(instance)  # 此时你应该明白,到底是谁在为你做自动传递self的事情


class Room:
    def __init__(self, name, width, length):
        self.name = name
        self.width = width
        self.length = length

    @Lazyproperty  # area=Lazyproperty(area)--->Lazyproperty类的__init__执行,把area放到了Lazyproperty的对象中然后返回了-->area代指Lazyproperty的对象
    def area(self):
        return self.width * self.length


r1 = Room('xxx', 2, 3)
# r1.area是Lazyproperty的对象,类是描述符类---->r1.area会触发描述符类的 __get__方法
print(r1.area)  # 触发描述符类的 __get__ 的执行
print(r1.area)  # 触发描述符类的 __get__ 的执行
print(r1.area)  # 触发描述符类的 __get__ 的执行

自己定制一个classmethod装饰器

class ClassMethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):  # 类来调用,instance为None,owner为类本身,实例来调用,instance为实例,owner为类本身,
        def feedback():
            print('在这里可以加功能啊...')
            return self.func(owner)

        return feedback


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

    @ClassMethod  # get_obj=ClassMethod(get_obj)--->ClassMethod的对象
    def get_obj(cls):
        print(cls)
        print('这是类的绑定方法')


# People.get_obj   # 触发 描述符类的__get__,--->返回feedback的内存地址
People.get_obj()  # 其实执行的是feedback()--->self.func--->People类的get_obj方法,self.func(类)--->get_obj(People传入了)

自己定制一个staticmethod装饰器

class StaticMethod:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        def feedback():
            print('在这里可以加功能啊...')
            return self.func()

        return feedback


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

    @StaticMethod  # get_obj=StaticMethod(get_obj)--->StaticMethod的对象
    def get_obj():
        print('这是静态方法')


# People.get_obj # --->触发__get__执行----feedback内存地址

People.get_obj()  # feedback()
  • 带有参数的情况下
Method:
    def __init__(self, func):
        self.func = func

    def __get__(self, instance, owner):
        def feedback(*args, **kwargs):
            print('在这里可以加功能啊...')
            return self.func(*args, **kwargs)

        return feedback


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

    @StaticMethod  # get_obj=StaticMethod(get_obj)--->StaticMethod的对象
    def get_obj(a, b):
        print(a, b)
        print('这是静态方法')


# People.get_obj # --->触发__get__执行----feedback内存地址

People.get_obj(7, 8)  # feedback()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值