python笔记

菜鸟教程python3部分笔记

1 变量_

在交互模式中,最后被输出的表达式结果被赋值给变量 _
_
此处, _ 变量应被用户视为只读变量。

2 数学函数

数学函数

3 常用随机数函数

随机数函数

4 格式化字符串

在 Python 中,字符串格式化可以使用与 C 中 sprintf 函数一样的语法:
%格式化字符串
f-string 是 python3.6 之后版本添加的,称之为字面量格式化字符串,是新的格式化字符串的语法。
f-string 格式化字符串以 f 开头,后面跟着字符串,字符串中的表达式用大括号 {} 包起来,它会将变量或表达式计算后的值替换进去,实例如下:
f-string
在 Python 3.8 的版本中可以使用 = 符号来拼接运算表达式与结果:
在这里插入图片描述

5 列表函数与方法

列表函数
列表方法

6 元组不可变

所谓元组的不可变指的是元组所指向的内存中的内容不可变。
元组
从以上实例可以看出,重新整体赋值的元组 tup,绑定到新的对象了,不是修改了原来的对象。

7 集合

集合(set)是一个无序的不重复元素序列。
移除元素的方法有:

s.remove(x)

将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。

s.discard( x )

移除集合中的元素,且如果元素不存在,不会发生错误。

s.pop()

随机删除集合中的一个元素。
set 集合的 pop 方法会对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除。

8 print中使用end关键字

关键字end可以用于将结果输出到同一行,或者在输出的末尾添加不同的字符。

b=0
while b<5:
	print(b,end=',')
	b=b+2

其输出结果应为:

024

9 在Python中没有switch – case语句。

10 while…else

在 while … else 在条件语句为 false 时执行 else 的语句块。
while...else

11 range

range(5)指的是0,1,2,3,4
range(5,9)指的是5,6,7,8
range(0,10,3)指的是0,3,6,9
range(-10,-100,-30)指的是-10,-40,-70

12 pass

Python pass是空语句,是为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句,如下实例:
pass

13 迭代器与生成器

迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:
迭代器
迭代器的本质——也就是“构造一个和自然数序列一一对应的序列”
在迭代器实现的核心思想就是“数据用到的时候才生成”
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
关于迭代器与生成器的例子
这个背后实现机制是怎么样的,

  1. 当generator function被调用的时候,这个函数会返回一个generator对象之后什么都不做。
  2. 当next方法被调用的时候,函数就会开始执行直到yield所在的位置,计算出来的值在这个位置被返回,之后这个函数就停下了。之后再调用next方法的时候,函数继续执行,直到遇到下一个yield。
  3. 如果执行完的代码,还没有遇到yield,就会抛出StopIteration异常。
    关于迭代器与生成器的一篇文章

14 python中,类型属于对象,变量没有类型

a=[1,2,3]
a="runoob"

以上代码中,[1,2,3] 是 List 类型,“Runoob” 是 String 类型,而变量 a 是没有类型的,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。

15 参数传递

可变对象与不可变对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。

  • 不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
  • 可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

python 函数的参数传递:

  • 不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
  • 可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
    参数传递
    python 中一切都是对象,严格意义上我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

16 不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,声明时不会命名。
加了星号 *的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
不定长参数
还有一种就是参数带两个星号 ,加了两个星号 的参数会以字典的形式导入。
带两个星号的不定长参数导入
声明函数时,参数中星号 *可以单独出现,如果单独出现星号 ,后面的参数必须用关键字传入。
单独出现星号作为参数

17 匿名函数

匿名函数

18 强制位置参数(python3.8)

Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

def f(a,b,/,c,d,*,e,f):
	print(a,b,c,d,e,f)

以下使用方法是正确的:

f(1,2,3,d=4,e=5,f=6)

以下使用方法会发生错误:

f(1,b=2,c=3,d=4,5,f=6) #b不能使用关键字参数的形式,e必须使用关键字参数的形式

19 列表的方法

列表的方法

20 列表推导式

列表推导式提供了从序列创建列表的简单途径。通常应用程序将一些操作应用于某个序列的每个元素,用其获得的结果作为生成新列表的元素,或者根据确定的判定条件创建子序列。
例如:
列表推导式1
列表推导式2
列表推导式3
列表推导式4
列表推导式5

21 字典

字典的创建:

tel={'jack':111,'sape':222}
tel['guide']=333
dict([('sape',111),('guido',222)])  #使用构造函数dict直接从键值对元组列表中构建字典
{x:x**2 for x in (2,4,6)}  #字典推导可以用来创建任意键和值的表达式词典
dict(sape=111,guido=222,jack=333)  #如果关键字只是简单的字符串,使用关键字参数指定键值对有时候更方便

22 遍历技巧

在字典中遍历时,关键字和对应的值可以使用 items() 方法同时解读出来。

for k,v in knights.items():
	print(k,v)

在序列中遍历时,索引位置和对应值可以使用 enumerate() 函数同时得到。

for i,v in enumerate(['tic','tac','toe']):
	print(i,v)

同时遍历两个或更多的序列,可以使用 zip() 组合。

for q,a in zip(questions,answers):
	print(q,'   ',a)

23 __name__属性

一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

if __name__=='__main__':
	print('程序自身在运行')
else:
	print('我来自另一模块')

运行输出为:
__main__
说明: 每个模块都有一个__name__属性,当其值是__main__时,表明该模块自身在运行,否则是被引入。

24 dir()

内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回。

25 包,import,__ all __

包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。
这里给出了一种可能的包结构(在分层的文件系统中):
包结构举例
在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。
目录只有包含一个叫做 __ init __.py 的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块。最简单的情况,放一个空的 :file:init.py就可以了。当然这个文件中也可以包含一些初始化代码或者为(将在后面介绍的) __all__变量赋值。
我们可以:

import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4) #必须使用全名

或者

from sound.effects import echo #导入了子模块echo
echo.echofilter(input, output, delay=0.7, atten=4)

或者

from sound.effects.echo import echofilter #导入子模块echo,并且可以直接使用他的echofilter()函数
echofilter(input, output, delay=0.7, atten=4)

注意当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。
import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,抛出一个 :exc:ImportError 异常。
反之,如果使用形如 import item.subitem.subsubitem 这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。

如果我们使用 from sound.effects import *,Python 会进入文件系统,找到这个包里面所有的子模块,一个一个的把它们都导入进来。但是很不幸,这个方法在 Windows平台上工作的就不是非常好,因为Windows是一个大小写不区分的系统。在这类平台上,没有人敢担保一个叫做 ECHO.py 的文件导入为模块 echo 还是 Echo 甚至 ECHO。
为了解决这个问题,只能烦劳包作者提供一个精确的包的索引了。
导入语句遵循如下规则:如果包定义文件 __ init __.py 存在一个叫做 __ all __ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。
例如,在:file:sounds/effects/init.py中包含如下代码:

__all__ = ["echo", "surround", "reverse"]

这表示当你使用from sound.effects import *这种用法时,你只会导入包里面这三个子模块。
如果 all 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包sound.effects和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。
记住,使用 from Package import specific_submodule 这种方法永远不会有错。事实上,这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。
如果在结构中包是一个子包(比如这个例子中对于包sound来说),而你又想导入兄弟包(同级别的包)你就得使用导入绝对的路径来导入。比如,如果模块sound.filters.vocoder 要使用包 sound.effects 中的模块 echo,你就要写成 from sound.effects import echo。
无论是隐式的还是显式的相对导入都是从当前模块开始的。主模块的名字永远是"__ main __",一个Python应用程序的主模块,应当总是使用绝对路径引用。

26 输出 repr() .format()

repr(): 产生一个解释器易读的表达形式。
str.format() :格式化输出值。

repr和format
括号及其里面的字符 (称作格式化字段) 将会被 format() 中的参数替换,还可以在括号中使用位置参数与关键字参数。
输出空格格式

27 open()读写文件模式

读写文件
读写文件的模式
mode 参数是可选的; ‘r’ 将是默认值。

28 file方法

open()
完整的格式为:
open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
关于open()的各参数:看这个

29 有个模块叫os

Python os模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。
简单的来说它是一个Python的系统编程的操作模块,可以处理文件和目录这些我们日常手动需要做的操作。
在自动化测试中,经常需要查找操作文件,比如查找配置文件(从而读取配置文件的信息),查找测试报告等等,经常会对大量文件和路径进行操作,这就需要依赖os模块。

30 异常处理

try/except
try/except
以下例子中,让用户输入一个合法的整数,但是允许用户中断这个程序(使用 Control-C 或者操作系统提供的方法)。用户中断的信息会引发一个 KeyboardInterrupt 异常。

while True:
    try:
        x=int(input('请输入一个数字:'))
        break
    except ValueError:
        print("您输入的不是数字,请再次尝试输入!")

try 语句按照如下方式工作:

  • 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
  • 如果没有异常发生,忽略 except 子句,try 子句执行后结束。
  • 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
  • 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。

一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (RuntimeError,TypeError,NameError):
    pass

最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。

import sys
try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

try/except…else
try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。
else 子句将在 try 子句没有发生任何异常的时候执行。
try,except,else
以下实例在 try 语句中判断文件是否可以打开,如果打开文件时正常的没有发生异常则执行 else 部分的语句,读取文件内容:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到,而 except 又无法捕获的异常。
try-finally
try-finally 语句无论是否发生异常都将执行最后的代码。
try,except,else,finally
以下实例中 finally 语句无论异常是否发生都会执行:

try:
    runoob()
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('这句话,无论异常是否发生都会执行。')

raise
Python 使用 raise 语句抛出一个指定的异常。
raise
以下实例如果 x 大于 5 就触发异常:

x = 10
if x > 5:
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))

执行以上代码会触发异常:

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    raise Exception('x 不能大于 5。x 的值为: {}'.format(x))
Exception: x 不能大于 5。x 的值为: 10

用户自定义异常
你可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承,例如:

>>> class MyError(Exception):
        def __init__(self, value):
            self.value = value
        def __str__(self):
            return repr(self.value)
   
>>> try:
        raise MyError(2*2)
    except MyError as e:
        print('My exception occurred, value:', e.value)
   
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'

31 类 __init__()

类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用,像下面这样:

def __init__(self):
    self.data = []

当然, __init__() 方法可以有参数,参数通过 __init __() 传递到类的实例化操作上。例如:

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i)   # 输出结果:3.0 -4.5

32 类 self

self代表类的实例,而非类。
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

class Test:
    def prt(self):
        print(self)
        print(self.__class__)
t = Test()
t.prt()

以上实例执行结果为:

<__main__.Test object at 0x0000029128943748>
<class '__main__.Test'>

从执行结果可以很明显地看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的。
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('runoob',10,30)
p.speak()

33 类继承示例

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
    grade = ''
    def __init__(self,n,a,w,g):
        #调用父类的构函
        people.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
    topic = ''
    name = ''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
    a =''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
 
test = sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中排前的父类的方法

多继承时,需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
super() 函数是用于调用父类(超类)的一个方法。

34 类的私有属性与私有方法

类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
类的私有属性实例如下:

class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0    # 公开变量
    
    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print (self.__secretCount)
        
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount)  # 报错,实例不能访问私有变量

类的私有方法实例如下:

class Site:
    def __init__(self, name, url):
        self.name = name       # public
        self.__url = url   # private
 
    def who(self):
        print('name  : ', self.name)
        print('url : ', self.__url)
 
    def __foo(self):          # 私有方法
        print('这是私有方法')
 
    def foo(self):            # 公共方法
        print('这是公共方法')
        self.__foo()
 
x = Site('菜鸟教程', 'www.runoob.com')
x.who()        # 正常输出
x.foo()        # 正常输出
x.__foo()      # 报错

类的专有方法:
__init __ : 构造函数,在生成对象时调用
__del __ : 析构函数,释放对象时使用
__repr __ : 打印,转换
__setitem __ : 按照索引赋值
__getitem __: 按照索引获取值
__len __: 获得长度
__cmp __: 比较运算
__call __: 函数调用
__add __: 加运算
__sub __: 减运算
__mul __: 乘运算
__truediv __: 除运算
__mod __: 求余运算
__pow __: 乘方
Python同样支持运算符重载,我们可以对类的专有方法进行重载。

35 命名空间

命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。
一般有三种命名空间:
内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间。
如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常。

36 一些标准库

操作系统接口
os模块提供了不少与操作系统相关联的函数。
建议使用 “import os” 风格而非 “from os import *”。这样可以保证随操作系统不同而有所变化的 os.open() 不会覆盖内置函数 open()。
文件通配符
glob模块提供了一个函数用于从目录通配符搜索中生成文件列表。
命令行参数
通用工具脚本经常调用命令行参数。这些命令行参数以链表形式存储于 sys 模块的 argv 变量。
访问 互联网
有几个模块用于访问互联网以及处理网络通信协议。其中最简单的两个是用于处理从 urls 接收的数据的 urllib.request 以及用于发送电子邮件的 smtplib:

>>> from urllib.request import urlopen
>>> for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
...     line = line.decode('utf-8')  # Decoding the binary data to text.
...     if 'EST' in line or 'EDT' in line:  # look for Eastern Time
...         print(line)

<BR>Nov. 25, 09:43:32 PM EST

>>> import smtplib
>>> server = smtplib.SMTP('localhost')
>>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
... """To: jcaesar@example.org
... From: soothsayer@example.org
...
... Beware the Ides of March.
... """)
>>> server.quit()

注意第二个例子需要本地有一个在运行的邮件服务器。
日期和时间
datetime模块为日期和时间处理同时提供了简单和复杂的方法。
支持日期和时间算法的同时,实现的重点放在更有效的处理和格式化输出。
数据压缩
性能度量
timeit ,:mod:profile 和 pstats 模块。
测试模块
开发高质量软件的方法之一是为每一个函数开发测试代码,并且在开发过程中经常进行测试。
doctest模块提供了一个工具,扫描模块并根据程序中内嵌的文档字符串执行测试。
测试构造如同简单的将它的输出结果剪切并粘贴到文档字符串中。
通过用户提供的例子,它强化了文档,允许 doctest 模块确认代码的结果是否与文档一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值