A. python中的几种特殊数据类型小结
下面介绍了Python中的6种特殊数据类型:
1.list:列表
是一种有序的数据集合,在列表数据结构中的类型并不唯一
定义形式:L=['Micha',100,True]
输出整个列表的时候显示为['Micha',100,True]
输出单个的数值则为:Micha
a.访问,直接使用L[0]表示第一个元素或者使用L[-1]表示最后一个数据,以此类推,但是注意访问不能越界(访问的序号不能超过元素的总数)。
b.添加新元素:使用L.append(100)直接将100加入列表末尾,或者使用L.insert(0,'paul')将paul插入任意位置。
c.删除元素:L.pop()删除最后一个元素,或者L.pop(2)删除第2个位置的元素。
d.替换元素:直接赋值就可以了L[2]=100
2.tuple:元组
是一种有序的列表,但是其一旦创立完毕就不能够更改,即不能插入,删除里面的元素,访问的方式跟List结构一致。
a.t=()其打印后输出的形式是()
若t中的数据为一个数字则需要在后面加逗号,以区分普通数字,如t=(1,),打印出(1,)而非1,多元素的话则没有这个要求。
b.可以在不变的tuple中加入可变的List如t=(‘a’,'b',['A','B'])
3.dict:字典
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
len()函数可以计算任意集合的大小
其中可以简单地使用d[key]的形式来查找对应的value,这和list很像,不同之处是,list必须使用索引返回对应的元素,而dict使用key,当key不存在的时候,使用该key可能出现错误,因此:要避免KeyError发生,有两个办法:
一是先判断一下key是否存在,用in操作符:
if'Paul' in d:
print d['Paul']
如果'Paul'不存在,if语句判断为False,自然不会执行print d['Paul'],从而避免了错误。
二是使用dict本身提供的一个get方法,在Key不存在的时候,返回None:
>>>print d.get('Bart')
59
a.dict中的key不能重复,且dict中的存储的对应值没有顺序,打印出的东西可能是无序的
b.dict的更新:使用d[‘paul']=72求解
c.dict遍历:
d = {'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>>for key in d:
...print key
遍历只能获得key的值,需要通过key值获得对应的value
4.set:集合
无序但是所有元素唯一,不重复
a.定义:s = set(['A', 'B', 'C']),查看set的内容:
>>>print s
set(['A','C', 'B'])
可以用in来判断是否存在于集合中
b.遍历
s =set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
for xin s:
print x[0]+':',x[1]
c.添加元素到集合中
s.add(4)
d.删除元素
s.remove(4)若该元素不在集合中将会报错
5.Unicode编码
Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:
printu'中文'
注意:不加u,中文就不能正常显示中文。
a.转义形式:u'中文 日文 韩文'
b.输出多行:
u'''第一行
第二行'''
c.raw+多行的形式:
ur'''Python的Unicode字符串支持"中文",
"日文",
"韩文"等多种语言'''
如果中文字符串在Python环境下遇到UnicodeDecodeError,这是因为.py文件保存的格式有问题。可以在第一行添加注释
# -*-coding: utf-8 -*-
目的是告诉Python解释器,用UTF-8编码读取源代码。然后用Notepad++另存为, 并选择UTF-8格式保存。
6.raw的作用
如果一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。为了避免这种情况,我们可以在字符串前面加个前缀r,表示这是一个“raw”字符串,里面的字符就不需要转义了。例如:
r'(~_~)//'
但是r'...'表示法不能表示多行字符串,也不能表示包含'和"的字符串,如果要表示多行字符串。
B. Python变形
1.长宽表的变形
什么是长表?什么是宽表?这个概念是对于某一个特征而言的。例如:一个表中把性别存储在某一个列中, 那么它就是关于性别的长表;如果把性别作为列名,列中的元素是某一其他的相关特征数值,那么这个表是 关于性别的宽表。
1.1 pivot
pivot 是一种典型的长表变宽表的函数。对于一个基本的长变宽的操作而言,最重要的有三个要素,分别是变形后的行索引、需要转到列索引的列, 以及这些列和行索引对应的数值,它们分别对应了 pivot 方法中的 index, columns, values 参数。新生成表的 列索引是 columns 对应列的 unique 值,而新表的行索引是 index 对应列的 unique 值,而 values 对应了想 要展示的数值列。
利用 pivot 进行变形操作需要满足唯一性的要求,即由于在新表中的行列索引对应了唯一的 value ,因此原 表中的 index 和 columns 对应两个列的行组合必须唯一。例如,现在把原表中第二行张三的数学改为语文就 会报错,这是由于 Name 与 Subject 的组合中两次出现 (”San Zhang”, ”Chinese”) ,从而最后不能够确定到 底变形后应该是填写 80 分还是 75 分。
pandas 从 1.1.0 开始,pivot 相关的三个参数允许被设置为列表,这也意味着会返回多级索引。这里构造一 个相应的例子来说明如何使用:下表中六列分别为班级、姓名、测试类型(期中考试和期末考试)、科目、成 绩、排名。
根据唯一性原则,新表的行索引等价于对 index 中的多列使用 drop_plicates ,而列索引的长度为 values 中的元素个数乘以 columns 的唯一组合数量(与 index 类似)。
1.2 pivot_table
pivot 的使用依赖于唯一性条件,那如果不满足唯一性条件,那么必须通过聚合操作使得相同行列组合对应 的多个值变为一个值。例如,张三和李四都参加了两次语文考试和数学考试,按照学院规定,最后的成绩是 两次考试分数的平均值,此时就无法通过 pivot 函数来完成。
1.3 melt
长宽表只是数据呈现方式的差异,但其包含的信息量是等价的,前面提到了利用 pivot 把长表转为宽表,那 么就可以通过相应的逆操作把宽表转为长表,melt 函数就起到了这样的作用。
1.4 wide_to_long
melt 方法中,在列索引中被压缩的一组值对应的列元素只能代表同一层次的含义,即 values_name 。现在 如果列中包含了交叉类别,比如期中期末的类别和语文数学的类别,那么想要把 values_name 对应的 Grade 扩充为两列分别对应语文分数和数学分数,只把期中期末的信息压缩,这种需求下就要使用 wide_to_long 函数来完成。
2 索引的变形
2.1 stack 与 unstack
unstack 函数的作用是把行索引转为列索引
unstack 的主要参数是移动的层号,默认转化最内层,移动到列索引的最内层,同时支持同时转化多个层
类似于 pivot 中的唯一性要求,在 unstack 中必须保证 被转为列索引的行索引层和 被保留的行索引层构成 的组合是唯一的,例如把前两个列索引改成相同的破坏唯一性,那么就会报错
与 unstack 相反,stack 的作用就是把列索引的层压入行索引,其用法完全类似。
2.2 聚合与变形的关系
在上面介绍的所有函数中,除了带有聚合效果的 pivot_table 以外,所有的函数在变形前后并不会带来 values 个数的改变,只是这些值在呈现的形式上发生了变化。在上一章讨论的分组聚合操作,由于生成了新的行列 索引,因此必然也属于某种特殊的变形操作,但由于聚合之后把原来的多个值变为了一个值,因此 values 的 个数产生了变化,这也是分组聚合与变形函数的最大区别。
3 其他变形函数
3.1 crosstab
crosstab 并不是一个值得推荐使用的函数,因为它能实现的所有功能 pivot_table 都能完成,并且速度更快。 在默认状态下,crosstab 可以统计元素组合出现的频数,即 count 操作。例如统计 learn_pandas 数据集中 学校和转系情况对应的频数
3.2 explode
explode 参数能够对某一列的元素进行纵向的展开,被展开的单元格必须存储 list, tuple, Series, np.ndarray 中的一种类型。
3.3 get_mmies
get_mmies 是用于特征构建的重要函数之一,其作用是把类别特征转为指示变量。例如,对年级一列转为 指示变量,属于某一个年级的对应列标记为 1,否则为 0
C. Python 数据模型
Python 风格的关键完全体现在 Python 的数据模型上,数据模型所描述的 API ,为使用最地道的语言特性来构建开发者自己的对象提供了工具。
当 Python 解析器遇到特殊句法时,会使用特殊方法去激活一些基本的对象操作。特殊方法以双下划线开头,以双下划线结尾。如: obj[key] 的背后就是 __getitem__ 方法。魔术方法是特殊方法的昵称,特殊方法也叫双下方法。
使用 __getitem__ 和 __len__ 创建一摞有序的纸牌:
上面的例子,使用 collections.namedtuple 构建了一个简单的类来表示一张纸牌, namedtuple 用以构建只有少数属性但没有方法的类。
我们自定义的 FrenchDeck 类可以像任何 python 标准集合类型一样使用 len() 函数,查看一叠牌有多少张:
也可以像列表一样,使用位置索引, d[i] 将调用 __getitem__ 方法:
也可以使用标准库模块提供的 random.choice 方法,从序列中随机选取一个元素。下面,我们如随机取出一张纸牌:
现在我们已经体会到通过 python 特殊方法,来使用 Python 数据模型的 2 个好处:
因为 __getitem__ 方法把 [] 操作交给了 self.cards 列表,所以我们的 FrenchDeck 实例自动支持切片:
仅仅实现了 __getitem__ 方法,这一摞牌即变得可迭代:
运行结果:
也可以直接调用内置的 reversed 函数,反向迭代 FrenchDeck 实例:
运行结果:
迭代通常是隐式的,比如一个集合类型没有实现 __contains__ 方法,那么 in 运算符就会按顺序做一次迭代搜索。
因此, in 运算符可以用在我们的 FrenchDeck 实例上,因为它是可迭代的:
FrenchDeck 还可以使用 Python 标准库中的 sorted 函数,实现排序:
首先定义一个排序依据的函数:
优先按 rank 的大小排序,rank 相同时则比较 suit 的值:
运行结果:
优先按 suit 的大小排序,suit 相同时则比较 rank 的值:
运行结果:
按照目前的设计,FrenchDeck 还不支持洗牌,因为它是不可变的:
shuffle 函数要调换集合中元素的位置,而 FrenchDeck 只实现了不可变的序列协议,可变的序列还必须提供 __setitem__ 方法:
洗牌:
没有任何的返回值,可见 random.shuffle 就地修改了可变序列 d 。为便于观察结果,我们定义输入的输出函数:
运行结果:
每次洗牌,都是一个随机的序列:
首先明确一点,特殊方法的存在是为了被 Python 解析器调用的,例如:我们不会使用 obj.__len__() 这种写法,而是 len(obj) 。在执行 len(obj) 时,如果 obj 是一个自定义类的对象,那么 Python 会自己去调用我们实现的 __len__ 方法。
对于 Python 内置的数据类型,比如列表、字符串、字节序列等,那么 CPython 会抄个近路, __len__ 实际上会返回 PyVarObject 里的 ob_size 属性,这是因为直接读取属性比调用一个方法要快得多。
很多时候,特殊方法的调用是隐式的,比如 for i in x: 这个语句其实是调用 iter(x) ,而这个函数的背后是 x.__iter__() 方法。
通过内置函数如来使用特殊方法是最好的选择。这些内置函数不仅会调用这些方法,通常还提供额外的好处,对于内置类型来说,它们的速度更快。
下面,我们通过定义一个简单的二维向量类,再来体会一下 Python 特殊方法的美妙:
使用 Vector 类,就像使用 Python 内置的数据类型一样简单:
D. Python3 & 基本数据类型(一)
Python提供的基本数据类型:数值(整型、浮点型、复数、布尔型等)、字符串、列表、元组、字典、集合等,将它们简单分类如下:
通常被称为整型,数值为正或者负,不带小数点。
Python 3的整型可以当做Long类型使用,所以Python 3没有
Python 2的Long类型。
Python 初始化的时候会自动建立一个小整数对象池,方便我们调用,避免后期重复生成!这是一个包含 262个指向整数对象的指针数组,范围是 -5 到 256 。
Python的浮点数就是数学中的小数,类似C语言中的double。
浮点数 也就是小数,如 1.23 , 3.14 , -9.01 等等。但是对于很大或很小的浮点数,一般用科学计数法表示,把10用e替代, 1.23x10^9 就是 1.23e9 ,或者 12.3e8 , 0.000012 可以写成1.2e-5 等等。
复数 由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示,复数的实部a和虚部b都是浮点。
对 与 错 、 0 和 1 、 正 与 反 ,都是传统意义上的布尔类型。
但在Python语言中,布尔类型只有两个值, True 与 False 。请注意,是英文单词的对与错,并且首字母要大写。
在Python中,0、0.0、-0.0、None、空字符串“”、空元组()、空列表[]、空字典{}都被当作False,还有自定义类型,如果实现了 nonzero ()或 len ()方法且方法返回0或False,则其实例也被当作False,其他对象均为True
布尔值还可以用and、or和not运算。
1)、and 运算是 与 运算,只有所有都为 True , and 运算的结果才是 True ;
2)、or 运算是 或 运算,只要其中有一个为 True , or 运算结果就是 True ;
3)、not 运算是 非 运算,它是单目运算符,把 True 变成 False,False 变成 True。
例如:
由以上案例可以看出,在做四则运算的时候,明显把 True 看做 1 , False 看做 0 。
4)空值
空值不是布尔类型,只不过和布尔关系比较紧密。
空值是Python里一个特殊的值,用 None 表示(首字母大写)。None不能理解为0,因为0是整数类型,而None是一个特殊的值。None也不是布尔类型,而是NoneType。
在某些特定的情况下,需要对数字的类型进行转换。
Python提供了内置的数据类型转换函数:
int(x) 将x转换为一个整数。如果x是一个浮点数,则截取小数部分。
float(x) 将x转换成一个浮点数。
complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
complex(x, y): 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。
Python字符串即可以用单引号也可以用双引号括起来,甚至还可以用三引号括起来,字符串是以''或""括起来的任意文本。
例如:'abc',"xyz"等等。请注意,''或""本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c这3个字符。如果'本身也是一个字符,那就可以用""括起来,比如"I'm OK"包含的字符是I,',m,空格,O,K这6个字符。
字符串中包括特殊字符,可以用转义字符来标识
但是字符串里面如果有很多字符都需要转义,就需要加很多,为了简化,Python还允许用r''表示''内部的字符串默认不转义
例如:
print r'\ \' #输出:\ \
字符串的一些常见操作
切⽚是指对操作的对象截取其中⼀部分的操作
语法:序列[开始位置下标:结束位置下标:步⻓]
a. 不包含结束位置下标对应的数据, 正负整数均可;
b. 步⻓是选取间隔,正负整数均可,默认步⻓为1。
find():检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则则返回-1。
index():检测某个⼦串是否包含在这个字符串中,如果在返回这个⼦串开始的位置下标,否则则报异常。
rfind(): 和find()功能相同,但查找⽅向为右侧开始。
rindex():和index()功能相同,但查找⽅向为右侧开始。
count():返回某个⼦串在字符串中出现的次数。
replace():替换
split():按照指定字符分割字符串。
join():⽤⼀个字符或⼦串合并字符串,即是将多个字符串合并为⼀个新的字符串。
capitalize():将字符串第⼀个字符转换成⼤写。
title():将字符串每个单词⾸字⺟转换成⼤写。
lower():将字符串中⼤写转⼩写。
upper():将字符串中⼩写转⼤写。
lstrip():删除字符串左侧空⽩字符。
rstrip():删除字符串右侧空⽩字符。
strip():删除字符串两侧空⽩字符。
ljust():返回⼀个原字符串左对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串。
rjust():返回⼀个原字符串右对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串,语法和
ljust()相同。
center():返回⼀个原字符串居中对⻬,并使⽤指定字符(默认空格)填充⾄对应⻓度 的新字符串,语
法和ljust()相同。
所谓判断即是判断真假,返回的结果是布尔型数据类型:True 或 False。
startswith():检查字符串是否是以指定⼦串开头,是则返回 True,否则返回 False。如果设置开
始和结束位置下标,则在指定范围内检查。
endswith()::检查字符串是否是以指定⼦串结尾,是则返回 True,否则返回 False。如果设置开
始和结束位置下标,则在指定范围内检查。
isalpha():如果字符串⾄少有⼀个字符并且所有字符都是字⺟则返回 True, 否则返回 False。
isdigit():如果字符串只包含数字则返回 True 否则返回 False。
isalnum():如果字符串⾄少有⼀个字符并且所有字符都是字⺟或数字则返 回 True,否则返回
False。
E. Python魔法函数(特殊函数)
Python中如何实现运算符的重载,即实现例如a+b这样的运算符操作呢?
在C++中可以使用 operator 关键字实现运算符的重载。但是在Python中没有类似这样的关键字,所以要实现运算符的重载,就要用到Python的魔法函数。Python魔法函数是以双下划线开头,双下划线结尾的一组函数。我们在类定义中最常用到的 __init__ 函数就是这样一个魔法函数,它在创建类对象时被自动调用。
下面我们来看个简单的例子。
上述代码示例了几个魔法函数的用法。 __add__ 函数对应了二元运算符+,当执行a+b语句时,python就会自动调用a. add (b)。 对于上述例子中的v1+v2+v3,则相当于调用了(v1. add(v2)). add(v3)。
代码中还有一个在Python类定义经常使用的 __str__ 函数,当使用 str() 时会被调用。print函数对传入的参数都调用了str()将其转换成易读的字符串形式,便于打印输出,因而会调用类定义的__str__函数打出自定义的字符串。
代码中还有一个特殊的 __call__ 函数,该函数在将对象采用函数调用方式使用时被调用, 例如v1()相当于v1. call ()。
以上就是魔法函数的基本使用方法。常见的魔法函数我们可以使用 dir() 函数来查看。
输出结果为:
上述结果中形式为‘__函数名__’的函数为魔法函数,注意有些对象也是这种形式,例如__class__, __mole__等, 这些不是魔法函数。具体的魔法函数说明可以参考Python官方说明文档。
以上代码在Python3.6运行通过.
F. python特殊符号的更改,替换
def secname(name):
SecName = name.replace('/', '')
SecName = SecName.replace('*', '')
SecName = SecName.replace('<', '(')
SecName = SecName.replace('>', ')')
SecName = SecName.replace('"', '')
SecName = SecName.replace(':', '-')
SecName = SecName.replace('\\', '')
SecName = SecName.replace('|', '')
SecName = SecName.replace('?', '')
return SecName
G. Python编程语言有何特殊性
从理论上来说,只要有合适的硬件驱动和API,编程语言都是可以做任何开发的,只有合不合适的问题。
先说一下编程语言的老大哥C/C++,这是很多人最开始学习的两门语言,C/C++的特点就是效率高,基本上是所有编程语言里效率最高的,而且一般系统中都具备C/C++编译器;
目前,C语言主要用来开发底层模块,服务应用和嵌入式应用,比如驱动、解码器、算法实现、Web服务器等;
当然C++也可以做这些,不过由于C++的复杂性和标准问题,程序员还是更愿意使用C来做,C++更适合比较复杂但又特别需要高效率的程序,比如大型游戏、基础库、大型桌面应用等。
再来说说Java,这是一门历史悠久的编程语言,可谓是很多Web应用程序、桌面程序、操作系统的立足之本,多年来霸占着编程语言排行榜的榜首;Java具备一些很好的语言特性,以及丰富的框架,在企业应用中备受青睐,因为Java能做的东西很多,游戏、网站都不在话下,在手机领域也有一席之地;尤其是智能手机爆发之后,Java的手机主场就变成了Android,一度作为Android的标准开发编程语言而存在。
然后来说说PHP,这是一种被广泛应用的开源通用脚本语言,适用于Web开发并且可嵌入到HTML中,主要目标就是允许Web开发人员快速编写动态生成的Web页面,但PHP的用途远不只是这些,PHP还包含了命令列执行接口和产生图形使用者接口程式。
最后来说说我们的重头戏,Python语言。这对于初学者来说是一个入门级编程语言,由于具有丰富和强大的库,又被叫做胶水语言,能够把其他语言制作的各种模块很轻松地联结在一起。
关于Python编程语言有何特殊性,环球青藤小编就和大家分享到这里了,学习是永无止境的,学习一项技能更是受益终身,所以,只要肯努力学,什么时候开始都不晚。如果您还想继续了解关于python编程的学习方法及素材等内容,可以点击本站其他文章学习。
H. python字符串(特殊字符,取值,常用方法)
1.字符串
特殊字符串
\n:换行
\r:删除\r前面的字符
\t:制表符
例如:
s_1 = "人生苦短,\n我选Python!"
s_2 = "人生苦短,\r我选Python!"
s_3 = "人生苦短,\t我选Python!"
print(s_1) # 人生苦短,
print(s_2) # 我选Python
print(s_3) # 人生苦短, 我选Python!
遇到特殊字符,想去掉效果,把特殊字符转成普通字符
可以使用# r R
s_1 =r "人生苦短,\n我选Python!"
s_2 =R "人生苦短,\r我选Python!"
s_3 = "人生苦短,\t我选Python!"
2.字符串取值
特点:取头不取尾,正序从0开始,倒序从-1开始
[start:end:step] #step:表示间隔
s='hello python lemon'
print(s[6:12:1]) #正序 python 6,7,8,9,10,11
print(s[-12:-6:1]) # 倒序 python -12,-11,-10,-9,-8,-7
print(s[:])#hello python lemon 从头取到尾 [:]
print(s[6:]) #python lemon 从6取到尾 [start:]
print(s[:17])# [:end] 从开始取到16
获取s所有的偶数位的字母
print(s[0:17:2])
获取s所有的奇数位的字母
print(s[1:18:2])
倒序输出所有的字母
print(s[17::-1]) # 不可以写出是s[17:-1:-1] or s[17:0:-1]
3.常用方法
find() : 返回-1表示未找到子字符串,找到会返回对应字符的索引,子字符包含单个字符或多个字符
isdigit():判断是否全部是数字,是返回True,否返回False
replace(要替换的内容:替换的内容:替换的次数):指定替换内容以及被替换的字符串,并可以指定替换次数,默认是全部替换
split(指定字符,指定切割的次数):根据指定字符对字符串进行切割,默认全部切割
strip():去掉头和尾指定的字符
upper():字符串的字母转成大写
lower():字符串的字母转成小写
swapcase():字符串的字母大小互换
例如:
s='learn python in lemon'
print(s.find('n')) #返回找到字符串的索引
print(s.find(python))#返回找到的子字符串的第一个索引值--6
print(s.find('k')) # 返回-1
print(s.find('o',11))#从索引值为11的值开始找---19
print(s.isdigit())# 返回False
s1 = "******learn python*****"
print(s.strip("*"))# learn python
I. python中特殊字符的替换
1、用字符串本身的replace方法
复制代码代码如下:
a.replace('word','python')
输出的结果是hello python
2、用正则表达式来完成替换:
复制代码代码如下:
import re
strinfo = re.compile('word')
b = strinfo.sub('python',a)
print b
输出的结果也是hello python
至于用哪个方法的话,看你自己的选择了。
J. python元编程中一些处理属性的特殊方法
在用户自己定义的类中,下述特殊方法用于获取、设置、删除和列出属性
使用点号,或者内置的的getattr,hasattr, setattr函数存取属性都会触发下述列表中的特殊方法。但是,直接通过实例的 __dict__ 属性来存取方法不会触发这些特殊方法。所以,如果需要,在一些情况下,可以使用这种方法跳过特殊方法。
示例,假设有个名为 Class 的类,obj 是 Class 类的实例,attr 是 obj 的属性。
obj.attr 和 getattr(obj, 'attr', 42)都会触发 Class.__getattribute__(obj, 'attr') 方法。尝试获取指定属性时总会调用这个方法,不过,寻找的属性时特殊属性或者特殊方法时除外。
del obj.attr 语句会触发 Class.__delattr__(obj, 'attr') 方法。
dir(obj)语句会触发 Class.__dir__(obj) 方法。
仅当获取指定的属性失败,搜索过 obj、Class 和超类之后调用 Class.__getattr__(self, name)
尝试设置指定的属性时总会调用 Class.__setattr__(obj, 'attr', value) ,点号和setattr(obj, 'attr', 42)会调用这个方法。