python之内置函数(一)

一、内置函数一
1、内置函数总览

 

abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()
delattr() hash() memoryview() set()

2、作用域相关 ******
globals() :返回一个字典(包含全部的全局变量)
locals() : 返回一个字典(包含的是当前作用域的所有变量)

复制代码
b = 2
a = 3
print(globals())
print(locals())
# 结果:这两个结果一样,因为都是在全局执行的。


def fun():
    a = 3
    b = 2
    print(globals())
    print(locals())
fun()
# 结果:
globals():
{'__name__': '__main__', '__doc__': None, '__package__': None, 
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000228CB787748>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
'__file__': 'E:/OldBoy/Knight/PythonProject/day13/t2.py', '__cached__': None, 'b': 2, 'a': 3, 
'fun': <function fun at 0x00000228CB351E18>}

locals():{'b': 2, 'a': 3}
复制代码


3、字符串类型代码的执行:eval,exec,compile (不建议使用 ***)

复制代码
eval: 执行字符串类型的代码,并返回最终结果
s1 = '1+2+3+4+5'
print(eval(s1),type(eval(s1)))  #15 <class 'int'>


s2 = "{'name':'xiaoming'}"
print(eval(s2),type(eval(s2)))  #{'name': 'xiaoming'} <class 'dict'>


s3 = 'print(666)'
eval(s3)   # 666
print(eval(s3))  # 666 None(执行s3里面的代码没有返回值,就返回None)

exec:执行字符串类型的代码,不返回结果(代码流)
s3 = 'print(666)'
exec(s3)  #666(没有返回值的代码流可用exec())


s4 = '''for i in range(10):
    print(i)
'''
exec(s4) # 0 1 2 3 4 5 6 7 8 9
eval(s4) # 报错

s1 = '1+2+3+4+5'
print(eval(s1),type(eval(s1)))  #15 <class 'int'>
print(exec(s1))  #None(有返回值不能用exec)


compile(了解即可):将字符串类型的代码编译。代码对象能够通过exec语句来执行或者eval()进行求值。
参数说明:   
1. 参数source:字符串或者AST(Abstract Syntax Trees)对象。即需要动态执行的代码段。  
2. 参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时,filename参数传入空字符即可。  
3. 参数model:指定编译代码的种类,可以指定为 ‘exec’,’eval’,’single’。当source中包含流程语句时,model应指定为‘exec’;
当source中只包含一个简单的求值表达式,model应指定为‘eval’;当source中包含了交互式命令语句,model应指定为'single'。 例子: #流程语句使用exec s5 = 'for i in range(5):print(i)' compile1 = compile(s5,'','exec') exec(compile1) 结果:0 1 2 3 4 #简单求值表达式用eval s5 = '1*2*3*4' compile2 = compile(s5,'','eval') print(eval(compile2)) 结果:24 #交互语句用single s5 = 'name = input("please input your name:")' compile3 = compile(s5,'','single') exec(compile3) #运行后会让用户进行输入,please input your name: print(name) #在exec(compile3)运行前没有值,运行后,值为用户输入的值。
复制代码

注意:有返回值的字符串形式的代码用eval,没有返回值的字符串形式的代码用exec,一般不用compile。
但是!一般不推荐使用这几个方法,为什么呢?
举个栗子:
  在工作中,别人发给你一个文本文件,你读文件的时候,读出来的都是字符串吧,那么就可以使用这三个方法,
但是,一旦你使用了这几个方法,它立马就执行了,你想过没有,如果别人在传送文件给你的时候,你的文件被
黑客截取了,植入了病毒,再发回给你,那你使用eval,exec不就把病毒也读取了吗?


4、输入输出相关 input(),print() *****
input:函数接受一个标准输入数据,返回为string类型。
print:打印输出。

print的参数分析:print(self, *args, sep=' ', end='\n', file=None)
1,*args:可接收多个位置参数
2,sep:打印多个值之间的分隔符,默认为空格
3,end:每一次打印的结尾,默认为换行符
4,file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件

1,*args:可接收多个位置参数
print('666')         # 666
print(1,2,3,4)     # 1 2 3 4
print(*[1,2,3])    # 1 2 3
拓展:

def func1(*args,**kwargs):          #在函数的定义 *参数 代表聚合。
  print(*args)          #args=(1,2,3,4)这里的*args不是在函数的定义中,
                 #所以代表的是(*(1,2,3,4)) 打散 结果输出:1,2,3,4
  print(args)           #args是一个元组,输出(1, 2, 3, 4)
  print(**kwargs)    #print(name='xiaoming',age=1000) print方法中没有**kwargs
                #不能接收多个关键字参数,所以这里会报错。
  print(kwargs)        #这里的kwargs是一个字典,print输出一个字典:{'name': 'xiaoming', 'age': 1000}
func1(1,2,3,4,name='xiaoming',age=1000)

2,sep:打印多个值之间的分隔符,默认为空格
print(1,2,3,sep='|')   # 1|2|3|4

3,end:每一次打印的结尾,默认为换行符
print(11,end=' ')
print(22)
结果:11 22

4,file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件
f = open('t1',encoding='utf-8',mode='w')
print(666,'777','888',file=f)

 

5、内存相关 hash id ***
hash:获取一个对象(可哈希对象(不可变类型):int,str,Bool,tuple)的哈希值。
id:获取该对象的内存地址。

print(hash('name')) # -163295680327498572
print(hash('name1')) # 9065259785983334233
print(hash(123)) # 123
print(hash(100000)) # 100000
print(hash(True)) # 1
print(hash(False)) # 0
print(hash([1,2,3])) #报错 列表是可变数据类型,是不可哈希的
注意:数字的哈希值就是数字本身!

小知识点:
  之前学字典的时候说过字典的优点之一是查询速度快,
  字典的查询甚至比二分查找还要快,为什么呢?
  字典的键是不可变的数据类型,所以是可哈希的,
  字典在存入内存的时候会将你的所有的key先进行哈希,再将哈希值存入内存中,
  这样在查询的时候可以根据哈希值直接就可以找到,所以查询速度很快!

 

6、文件操作相关 *****
open:函数用于打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。

7、模块相关 ***
__import__:函数用于动态加载类和函数 。

8、帮助 **
help:函数用于查看函数或模块用途的详细说明。
print(help(str))


9、调用相关
callable:函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;
但如果返回False,调用对象ojbect绝对不会成功。 ***
name = 'abc'

def fun():
  a = 2
  return a
print(callable(name))   #False 不可调用
print(callable(fun()))    #False 不可调用:fun()不是一个对象,它是函数的执行者
print(callable(fun))      #True 可调用:fun是一个对象


10、查看内置属性 ***
dir:函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;
带参数时,返回参数的属性、方法列表。
如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
s = 'a'
print(dir(s))

11、
range:函数可创建一个整数对象,一般用在 for 循环中。
python2x:   range(3) ---> [0,1,2] 列表
     xrange(3) ---> 迭代器
python3x:  range(3) ---> range(0,3) 可迭代对象

next:内部实际使用了__next__方法,返回迭代器的下一个项目
iter:函数用来生成迭代器(将一个可迭代对象,生成迭代器)

12、数字相关(14)
数据类型(4):
bool :用于将给定参数转换为布尔类型,如果没有参数,返回False。 ***
print(bool(1 < 2 and 3 > 4 or 5 < 6 and 9 > 2 or 3 > 1)) # True
print(bool('fdsjkfl')) #True


int:函数用于将一个字符串或数字转换为整型。***
print(int('123')) # 123
print(int(3.74)) # 取整并不是四舍五入:3
print(int('0101',base=2)) # 将2进制的0101转化成十进制,结果为5
  

float:函数用于将整数和字符串转换成浮点数。 ***
print(float(5))       # 5.0
print(float(3.16))  # 3.16
print(float('2'))     # 2.0
print(float('2.1'))  # 2.1
   
complex:函数用于创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。
如果第一个参数为字符串,则不需要指定第二个参数。。

13、进制转换(3):
bin:将十进制转换成二进制并返回。
print(bin(100)) # 0b1100100


oct:将十进制转化成八进制字符串并返回。
print(oct(7)) # 0o7
print(oct(8)) # 0o10
print(oct(9)) # 0o11


hex:将十进制转化成十六进制字符串并返回。
print(hex(10)) # 0xa
print(hex(15)) # 0xf
print(hex(17)) # 0x11


14、数学运算(7):
abs:函数返回数字的绝对值。 ****
print(abs(-100))     # 100

divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。 ****
print(divmod(12,7)) # (1, 5) (商,余数)

divmod的应用:分页。
假设有103条数据,你每页显示12条数据,你最终显示多少页。
print(divmod(103,12)) # (8,7) 即要9页,前8页,每页12条数据,最后一页,7条数据
    

round:保留浮点数的小数位数,默认保留整数,四舍五入。 ***
print(round(3.141592653))     #默认保留整数(会四舍五入):3
print(round(3.641592653))     #默认保留整数(会四舍五入):4
print(round(3.141592653,4))  #保留四位小数(会四舍五入):3.1416
print(round(3.141592653,2))  #保留两位小数(会四舍五入):3.14

    

pow:求x**y次幂。(三个参数为x**y的结果对z取余) **
print(pow(2,5))       # 2的5次幂:32
print(pow(2,5,12))  # 2的5次幂的结果对12取余(32对12取余):8
    

sum:对可迭代对象进行求和计算(可设置初始值)。 *****
sum(iterable,start_num)
print(sum([1,2,3,4,100,101]))          # 211
print(sum([1,2,3,4,100,101],100))   # 311(第二个参数为初始值)
print(sum([int(i) for i in [1,'2',3,'4','100',101]]))

    

min:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。 *****
print(min([1,-2,3,4,100,101]))                  # -2
print(min([1,-2,3,4,100,101],key=abs))   # 1

应用:
求出年龄最小的那个元组
ls = [('daming',1000),('xiaoming',18),('zhongming',500)]
这里的数据还不算复杂,可用之前学过的知识求出

min_age = min([i[1] for i in ls])
for j in ls:
    if j[1] == min_age:
        print(j)

但是有时候数据复杂的情况下,用之前的知识写,可能会很复杂。
这时可用min()方法,配合自定制的函数进行求值

def func(x):
    return x[1]  # 1000  18  500
print(min(ls,key=func))
# 结果:('xiaoming', 18)

min(可迭代对象,key=函数名):
1,它会将iterable的每一个元素当做函数的参数传进去。
2,它会按照返回值去比较大小。
3,最后返回的是遍历的元素 x

复制代码
dic = {'a':3,'b':2,'c':1}
def func1(x):
    return dic[x]
print(min(dic,key=func1))  
结果:c
# 这里传进去的元素是字典的键,比较的返回值是字典的值,最后返回的是遍历的键


def func2(x):
    return x[1]
print(min(dic.items(),key=func2))
结果:('c', 1)
# 这里传进去的元素是字典的键和值组成的元组,比较的返回值是字典的值,最后返回的是遍历的元组
复制代码

max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)。 *****
print(max([1,2,3,100]))    # 100

 

 

一、内置函数一
1、内置函数总览

 

abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()
delattr() hash() memoryview() set()

2、作用域相关 ******
globals() :返回一个字典(包含全部的全局变量)
locals() : 返回一个字典(包含的是当前作用域的所有变量)

复制代码
b = 2
a = 3
print(globals())
print(locals())
# 结果:这两个结果一样,因为都是在全局执行的。


def fun():
    a = 3
    b = 2
    print(globals())
    print(locals())
fun()
# 结果:
globals():
{'__name__': '__main__', '__doc__': None, '__package__': None, 
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000228CB787748>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
'__file__': 'E:/OldBoy/Knight/PythonProject/day13/t2.py', '__cached__': None, 'b': 2, 'a': 3, 
'fun': <function fun at 0x00000228CB351E18>}

locals():{'b': 2, 'a': 3}
复制代码


3、字符串类型代码的执行:eval,exec,compile (不建议使用 ***)

复制代码
eval: 执行字符串类型的代码,并返回最终结果
s1 = '1+2+3+4+5'
print(eval(s1),type(eval(s1)))  #15 <class 'int'>


s2 = "{'name':'xiaoming'}"
print(eval(s2),type(eval(s2)))  #{'name': 'xiaoming'} <class 'dict'>


s3 = 'print(666)'
eval(s3)   # 666
print(eval(s3))  # 666 None(执行s3里面的代码没有返回值,就返回None)

exec:执行字符串类型的代码,不返回结果(代码流)
s3 = 'print(666)'
exec(s3)  #666(没有返回值的代码流可用exec())


s4 = '''for i in range(10):
    print(i)
'''
exec(s4) # 0 1 2 3 4 5 6 7 8 9
eval(s4) # 报错

s1 = '1+2+3+4+5'
print(eval(s1),type(eval(s1)))  #15 <class 'int'>
print(exec(s1))  #None(有返回值不能用exec)


compile(了解即可):将字符串类型的代码编译。代码对象能够通过exec语句来执行或者eval()进行求值。
参数说明:   
1. 参数source:字符串或者AST(Abstract Syntax Trees)对象。即需要动态执行的代码段。  
2. 参数 filename:代码文件名称,如果不是从文件读取代码则传递一些可辨认的值。当传入了source参数时,filename参数传入空字符即可。  
3. 参数model:指定编译代码的种类,可以指定为 ‘exec’,’eval’,’single’。当source中包含流程语句时,model应指定为‘exec’;
当source中只包含一个简单的求值表达式,model应指定为‘eval’;当source中包含了交互式命令语句,model应指定为'single'。 例子: #流程语句使用exec s5 = 'for i in range(5):print(i)' compile1 = compile(s5,'','exec') exec(compile1) 结果:0 1 2 3 4 #简单求值表达式用eval s5 = '1*2*3*4' compile2 = compile(s5,'','eval') print(eval(compile2)) 结果:24 #交互语句用single s5 = 'name = input("please input your name:")' compile3 = compile(s5,'','single') exec(compile3) #运行后会让用户进行输入,please input your name: print(name) #在exec(compile3)运行前没有值,运行后,值为用户输入的值。
复制代码

注意:有返回值的字符串形式的代码用eval,没有返回值的字符串形式的代码用exec,一般不用compile。
但是!一般不推荐使用这几个方法,为什么呢?
举个栗子:
  在工作中,别人发给你一个文本文件,你读文件的时候,读出来的都是字符串吧,那么就可以使用这三个方法,
但是,一旦你使用了这几个方法,它立马就执行了,你想过没有,如果别人在传送文件给你的时候,你的文件被
黑客截取了,植入了病毒,再发回给你,那你使用eval,exec不就把病毒也读取了吗?


4、输入输出相关 input(),print() *****
input:函数接受一个标准输入数据,返回为string类型。
print:打印输出。

print的参数分析:print(self, *args, sep=' ', end='\n', file=None)
1,*args:可接收多个位置参数
2,sep:打印多个值之间的分隔符,默认为空格
3,end:每一次打印的结尾,默认为换行符
4,file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件

1,*args:可接收多个位置参数
print('666')         # 666
print(1,2,3,4)     # 1 2 3 4
print(*[1,2,3])    # 1 2 3
拓展:

def func1(*args,**kwargs):          #在函数的定义 *参数 代表聚合。
  print(*args)          #args=(1,2,3,4)这里的*args不是在函数的定义中,
                 #所以代表的是(*(1,2,3,4)) 打散 结果输出:1,2,3,4
  print(args)           #args是一个元组,输出(1, 2, 3, 4)
  print(**kwargs)    #print(name='xiaoming',age=1000) print方法中没有**kwargs
                #不能接收多个关键字参数,所以这里会报错。
  print(kwargs)        #这里的kwargs是一个字典,print输出一个字典:{'name': 'xiaoming', 'age': 1000}
func1(1,2,3,4,name='xiaoming',age=1000)

2,sep:打印多个值之间的分隔符,默认为空格
print(1,2,3,sep='|')   # 1|2|3|4

3,end:每一次打印的结尾,默认为换行符
print(11,end=' ')
print(22)
结果:11 22

4,file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件
f = open('t1',encoding='utf-8',mode='w')
print(666,'777','888',file=f)

 

5、内存相关 hash id ***
hash:获取一个对象(可哈希对象(不可变类型):int,str,Bool,tuple)的哈希值。
id:获取该对象的内存地址。

print(hash('name')) # -163295680327498572
print(hash('name1')) # 9065259785983334233
print(hash(123)) # 123
print(hash(100000)) # 100000
print(hash(True)) # 1
print(hash(False)) # 0
print(hash([1,2,3])) #报错 列表是可变数据类型,是不可哈希的
注意:数字的哈希值就是数字本身!

小知识点:
  之前学字典的时候说过字典的优点之一是查询速度快,
  字典的查询甚至比二分查找还要快,为什么呢?
  字典的键是不可变的数据类型,所以是可哈希的,
  字典在存入内存的时候会将你的所有的key先进行哈希,再将哈希值存入内存中,
  这样在查询的时候可以根据哈希值直接就可以找到,所以查询速度很快!

 

6、文件操作相关 *****
open:函数用于打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。

7、模块相关 ***
__import__:函数用于动态加载类和函数 。

8、帮助 **
help:函数用于查看函数或模块用途的详细说明。
print(help(str))


9、调用相关
callable:函数用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;
但如果返回False,调用对象ojbect绝对不会成功。 ***
name = 'abc'

def fun():
  a = 2
  return a
print(callable(name))   #False 不可调用
print(callable(fun()))    #False 不可调用:fun()不是一个对象,它是函数的执行者
print(callable(fun))      #True 可调用:fun是一个对象


10、查看内置属性 ***
dir:函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;
带参数时,返回参数的属性、方法列表。
如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
s = 'a'
print(dir(s))

11、
range:函数可创建一个整数对象,一般用在 for 循环中。
python2x:   range(3) ---> [0,1,2] 列表
     xrange(3) ---> 迭代器
python3x:  range(3) ---> range(0,3) 可迭代对象

next:内部实际使用了__next__方法,返回迭代器的下一个项目
iter:函数用来生成迭代器(将一个可迭代对象,生成迭代器)

12、数字相关(14)
数据类型(4):
bool :用于将给定参数转换为布尔类型,如果没有参数,返回False。 ***
print(bool(1 < 2 and 3 > 4 or 5 < 6 and 9 > 2 or 3 > 1)) # True
print(bool('fdsjkfl')) #True


int:函数用于将一个字符串或数字转换为整型。***
print(int('123')) # 123
print(int(3.74)) # 取整并不是四舍五入:3
print(int('0101',base=2)) # 将2进制的0101转化成十进制,结果为5
  

float:函数用于将整数和字符串转换成浮点数。 ***
print(float(5))       # 5.0
print(float(3.16))  # 3.16
print(float('2'))     # 2.0
print(float('2.1'))  # 2.1
   
complex:函数用于创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。
如果第一个参数为字符串,则不需要指定第二个参数。。

13、进制转换(3):
bin:将十进制转换成二进制并返回。
print(bin(100)) # 0b1100100


oct:将十进制转化成八进制字符串并返回。
print(oct(7)) # 0o7
print(oct(8)) # 0o10
print(oct(9)) # 0o11


hex:将十进制转化成十六进制字符串并返回。
print(hex(10)) # 0xa
print(hex(15)) # 0xf
print(hex(17)) # 0x11


14、数学运算(7):
abs:函数返回数字的绝对值。 ****
print(abs(-100))     # 100

divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。 ****
print(divmod(12,7)) # (1, 5) (商,余数)

divmod的应用:分页。
假设有103条数据,你每页显示12条数据,你最终显示多少页。
print(divmod(103,12)) # (8,7) 即要9页,前8页,每页12条数据,最后一页,7条数据
    

round:保留浮点数的小数位数,默认保留整数,四舍五入。 ***
print(round(3.141592653))     #默认保留整数(会四舍五入):3
print(round(3.641592653))     #默认保留整数(会四舍五入):4
print(round(3.141592653,4))  #保留四位小数(会四舍五入):3.1416
print(round(3.141592653,2))  #保留两位小数(会四舍五入):3.14

    

pow:求x**y次幂。(三个参数为x**y的结果对z取余) **
print(pow(2,5))       # 2的5次幂:32
print(pow(2,5,12))  # 2的5次幂的结果对12取余(32对12取余):8
    

sum:对可迭代对象进行求和计算(可设置初始值)。 *****
sum(iterable,start_num)
print(sum([1,2,3,4,100,101]))          # 211
print(sum([1,2,3,4,100,101],100))   # 311(第二个参数为初始值)
print(sum([int(i) for i in [1,'2',3,'4','100',101]]))

    

min:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。 *****
print(min([1,-2,3,4,100,101]))                  # -2
print(min([1,-2,3,4,100,101],key=abs))   # 1

应用:
求出年龄最小的那个元组
ls = [('daming',1000),('xiaoming',18),('zhongming',500)]
这里的数据还不算复杂,可用之前学过的知识求出

min_age = min([i[1] for i in ls])
for j in ls:
    if j[1] == min_age:
        print(j)

但是有时候数据复杂的情况下,用之前的知识写,可能会很复杂。
这时可用min()方法,配合自定制的函数进行求值

def func(x):
    return x[1]  # 1000  18  500
print(min(ls,key=func))
# 结果:('xiaoming', 18)

min(可迭代对象,key=函数名):
1,它会将iterable的每一个元素当做函数的参数传进去。
2,它会按照返回值去比较大小。
3,最后返回的是遍历的元素 x

复制代码
dic = {'a':3,'b':2,'c':1}
def func1(x):
    return dic[x]
print(min(dic,key=func1))  
结果:c
# 这里传进去的元素是字典的键,比较的返回值是字典的值,最后返回的是遍历的键


def func2(x):
    return x[1]
print(min(dic.items(),key=func2))
结果:('c', 1)
# 这里传进去的元素是字典的键和值组成的元组,比较的返回值是字典的值,最后返回的是遍历的元组
复制代码

max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)。 *****
print(max([1,2,3,100]))    # 100

 

 

猜你喜欢

转载自www.cnblogs.com/yidashi110/p/10092274.html