Python的数据类型与结构

标准数据类型

Python3 中有六个标准的数据类型:

  • Number(数字)
  • String(字符串)
  • List(列表)
  • Tuple(元组)
  • Set(集合)
  • Dictionary(字典)

其中:

  • 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
  • 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。

        序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。Python有6个序列的内置类型,但最常见的是列表和元组。序列都可以进行的操作包括索引,切片,加,乘,检查成员。此外,Python已经内置确定序列的长度以及确定最大和最小的元素的方法。

1、字母数字的ASCII码大小:“a-z”>"A-Z">"0-9",类似元组,字符串,列表的大小比较:先从第一个元素开始逐个比较,复数不能比较大小。

2、Python中:a=b属于浅拷贝,指向同一片内存。以字典为例:

  

所以我们最好先提前创建一个空的字典或其他数据类型,提前为其分配内存,这样防止发生浅拷贝

3、[:-1]表示倒序查看。

4、python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值'来传递对象

一、数字

     Python3 支持 int、float、bool、complex(复数)。在Python 3里,只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。内置的 type() 函数可以用来查询变量所指的对象类型。

      数据类型是不允许改变的,这就意味着如果改变数字数据类型的值,将重新分配内存空间。

,

 1、数字类型转换

数据类型的转换,只需要将数据类型作为函数名即可。

  • int(x) 将x转换为一个整数。
  • float(x) 将x转换到一个浮点数。
  • complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
  • complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。x 和 y 是数字表达式。复数不能比较大小

2、运算

表达式的语法很直白: +, -, * 和 /, 和其它语言里一样。不同类型的数混合运算时会将整数转换为浮点数.

  • 运算符 / :总是返回一个浮点数注意:在不同的机器上浮点运算的结果可能会不一样)
  • 运算符 // :丢弃分数部分,返回整数(注意:// 得到的并不一定是整数类型的数,它与分母分子的数据类型有关系。)
  • 运算符% 返回除法的余数
  • 使用 ** 操作来进行幂运算
  • 等号 = 用于给变量赋值,Python可以同时为多个变量赋值,如a, b = 1, 2。
>>> 17 / 3  # 整数除法返回浮点型
5.666666666666667

>>> 17 // 3  # 整数除法返回向下取整后的结果
5
>>> 17.0 // 3  # 整数除法返回向下取整后的结果
5.0
>>> 17 % 3  # %操作符返回除法的余数
2

>>> 5 ** 2  # 5 的平方
25

注意:

在Python2中:除法默认向下取整:17/3=5,type为int,而在Python3中,是float小数。 

3、数学函数

函数返回值 ( 描述 )
abs(x)返回数字的绝对值,如abs(-10) 返回 10
ceil(x)返回数字的上入整数,如math.ceil(4.1) 返回 5
exp(x)返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045
fabs(x)返回数字的绝对值,如math.fabs(-10) 返回10.0
floor(x)返回数字的下舍整数,如math.floor(4.9)返回 4
log(x)默认以e为底,如math.log(math.e)返回1.0,  math.log(100,10)返回2.0
log10(x)返回以10为基数的x的对数,如math.log10(100)返回 2.0
max(x1, x2,...)返回给定参数的最大值,参数可以为序列。
min(x1, x2,...)返回给定参数的最小值,参数可以为序列。
modf(x)返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。
pow(x, y)x**y 运算后的值。
round(x [,n])返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。
sqrt(x)返回数字x的平方根。

二、字符串

   字符串是 Python 中最常用的数据类型,Python严格区分大小写。我们可以使用引号( ' 或 " )来创建字符串。Python不支持单字符类型,单字符在 Python 中也是作为一个字符串使用。与 C 字符串不同的是,Python 字符串不能被改变。向一个索引位置赋值,比如word[0] = 'm'会导致错误。

1、访问

Python 访问子字符串,可以使用方括号来截取字符串,字符串的截取的语法格式如:    变量[头下标:尾下标]

索引值以 0 为开始值,-1 为从末尾的开始位置。

                                   

+字符串连接a + b 输出结果: HelloPython
*重复输出字符串,紧跟的数字为复制的次数a*2 输出结果:HelloHello
[]通过索引获取字符串中字符a[1] 输出结果 e
[ : ]截取字符串中的一部分,遵循左闭右开原则,str[0,2] 是不包含第 3 个字符的。a[1:4] 输出结果 ell
in成员运算符 - 如果字符串中包含给定的字符返回 True'H' in a 输出结果 True

实例如下:

str = 'Runoob'
 
print (str)          # 输出字符串
print (str[0:-1])    # 输出第一个到倒数第二个的所有字符
print (str[0])       # 输出字符串第一个字符
print (str[2:5])     # 输出从第三个开始到第五个的字符
print (str[2:])      # 输出从第三个开始的后的所有字符
print (str * 2)      # 输出字符串两次
print (str + "TEST") # 连接字符串

Runoob
Runoo
R
noo
noob
RunoobRunoob
RunoobTEST

2、字符串格式化

Python 支持格式化字符串的输出 。最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。在 Python 中,字符串格式化使用与 C 中 sprintf 函数一样的语法。

print("我叫 %s 今年 %d 岁!"%('小明',10))

输出结果:    我叫 小明 今年 10 岁!

python字符串格式化符号:

      %d 格式化整数
      %u 格式化无符号整型

在Python2中:

print r"\n"

 输出为:“\n”,。

这里“r”代表原始字符串标识符,表示特殊字符不会被转义。

3、字符串内建函数

Python 的字符串常用内建函数如下:

序号方法及描述
1

count(str, beg= 0,end=len(string))  返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数

2

str1.find(str, beg=0, end=len(string)) 检测 str1 是否含有字符串str中,如果指定范围 beg 和 end ,则检查是否包含在指定范围内,如果包含返回开始的索引值,否则返回-1

3

index(str, beg=0, end=len(string))   跟find()方法一样,只不过如果str不在字符串中会报一个异常.

4

len(string)   返回字符串长度

5

max(str)      返回字符串 str 中最大的字母。

6

min(str)        返回字符串 str 中最小的字母。

7

replace(old, new [, max])   把 将字符串中的 str1 替换成 str2,如果 max 指定,则替换不超过 max 次。

8

rfind(str, beg=0,end=len(string))  类似于 find()函数,不过是从右边开始查找.

9

rindex( str, beg=0, end=len(string))  类似于 index(),不过是从右边开始.

leetcode 3:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        i=0
        count=0
        for j in range(len(s)):

            if(s[j] not in s[i:j]):
                count=max(count,j-i+1)
            else:
                i=i+s[i:j].index(s[j])+1
        return count

 解法二:用集合类型

这道题主要用到思路是:滑动窗口。其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?我们只要把队列的左边的元素移出就行了,直到满足题目要求!一直维持这样的队列,找出队列出现最长的长度时候,求出解!

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:return 0
        left = 0
        lookup = set()
        n = len(s)
        max_len = 0
        cur_len = 0
        for i in range(n):
            cur_len += 1
            while s[i] in lookup:
                lookup.remove(s[left])
                left += 1
                cur_len -= 1
            if cur_len > max_len:max_len = cur_len
            lookup.add(s[i])
        return max_len

三、列表

    Python中列表是可变的,这是它区别于字符串和元组的最重要的特点。它可以作为一个方括号内的逗号分隔值出现。创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。

  1. 列表可以修改,而字符串和元组不能
  2. 列表的数据项不需要具有相同的类型,列表中的元素可以是Python中的任何对象
  3. 列表是有序的,每个元素的位置是确定的,可以用索引去访问每个元素
>>> x = [1,2,3]
>>> y = {'name':'Sakura'}
>>> z="Test"
>>> a=[x,y,z]
>>> a
[[1, 2, 3], {'name': 'Sakura'}, 'Test']  #列表中的元素可以是Python中的任何对象

      Python中的list和C语言中的数组蛮像的,只是list中的元素类型可以为Python中的任意对象,C中的数组只能是同种类型。当访问他们中的元素时,都可采用索引。这里需要注意的是,list不仅可以向数组那样正向索引也可以反向索引。 

               

1、访问列表中的值:

使用下标索引来访问列表中的值,也可以使用方括号的形式截取字符

Python 表达式结果描述
a[2]'Test'

读取第三个元素 

a[-2] {'name': 'Sakura'}从右侧开始读取倒数第二个元素: count from the right
a[1:][ {'name': 'Sakura'}, 'Test']输出从第二个元素开始后的所有元素

二维列表索引:a[0][0] = 1 

2、列表元素的增删改查             

对列表的数据项进行修改或更新:

list = ['Google', 'Runoob', 1997, 2000] 
list[2] = 2001 

使用append()方法来添加列表项,该方法无返回值,但是会修改原来的列表。:

list = ['Google', 'Runoob', 1997, 2000]
list.append('liuzhe')
print ("添加后的列表 : ", list)

实例输出结果:添加后的列表: ['Google', 'Runoob', 1997, 2000,'liuzhe'

使用 del 语句来删除列表的的元素,如下实例:

list = ['Google', 'Runoob', 1997, 2000]
del list[2]
print ("删除第三个元素 : ", list)

输出结果: 删除第三个元素 : ['Google', 'Runoob', 2000]

3、列表脚本操作符

列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。如下所示:

Python 表达式结果描述
len([1, 2, 3])3长度
[1, 2, 3] + [4, 5, 6][1, 2, 3, 4, 5, 6]组合
['Hi!'] * 4['Hi!', 'Hi!', 'Hi!', 'Hi!']重复
3 in [1, 2, 3]True元素是否存在于列表中
for x in [1, 2, 3]: print(x, end=" ")1 2 3迭代

 4、列表函数&方法

1list.append(obj)      在列表末尾添加新的对象
2list.count(obj)     统计某个元素在列表中出现的次数
3list.extend(seq)     在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
4list.index(obj)        从列表中找出某个值第一个匹配项的索引位置
5list.insert(index, obj)   将对象插入列表
6list.pop([index=-1])    移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
7list.remove(obj)        移除列表中某个值的第一个匹配项
8list.reverse()           将列表中元素翻转,反向
9list.sort( key=None, reverse=False)    对原列表进行排序          argsort()函数是numpy库中的
10list.clear() 清空列表
11list.copy() 复制列表
12len(list)    列表元素个数
13max(list)  返回列表元素最大值
14min(list)   返回列表元素最小值
15list(seq)   将元组转换为列表

5、列表当做堆栈使用

    堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来。例如:

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

6、将列表当作队列使用

      把列表当做队列用,只是在队列里第一加入的元素,第一个取出来;但是拿列表用作这样的目的效率不高。在列表的最后添加或者弹出元素速度快,然而在列表里插入或者从头部弹出速度却不快(因为所有其他的元素都得一个一个地移动)。

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")           # Terry arrives
>>> queue.append("Graham")          # Graham arrives
>>> queue.popleft()                 # The first to arrive now leaves
'Eric'
>>> queue.popleft()                 # The second to arrive now leaves
'John'
>>> queue                           # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])

7、列表推导式

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

       每个列表推导式都在 for 之后跟一个表达式,然后有零到多个 for 或 if 子句。返回结果是一个根据表达从其后的 for 和 if 上下文环境中生成出来的列表。如果希望表达式推导出一个元组,就必须使用括号。

这里我们将列表中每个数值乘三,获得一个新的列表:

vec = [2, 4, 6]
>>> [[x, x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]

8、常见查找方法

首先for循环是万能的,就不提了

8.1、找到列表中满足某些条件的元素 

a = [0, 1, 2, 3, 4, 0, 2, 3, 6, 7, 5]
selected = [x for x in a if x in range(1, 5)]   # 找到a中属于[1,5)中的元素

8.2、使用numpy库: np.where() 

 a = np.array([2,4,6,8,10])
>>> np.where(a > 5)             # 返回索引
(array([2, 3, 4]),) 

8.3、查找list相同元素的索引

list的index()方法是在list中找到第一个匹配的值。

a=[72, 56, 76, 84, 80, 88]
print(a.index(76))

2

     要是存在多个值 ,用for循环 print([i for i,m in enumerate(a)  if m==76])

 四、元组

Python 的元组与列表类似,下标索引从0开始,可以进行截取,组合等。不同之处:

  • 元组的元素不能修改
  • 元组使用小括号,列表使用方括号。

元组可以理解为一个固定的列表所以其内置的大多数的方法和列表是差不多的,元素可以是数字,string,list等。

1、元组的创建:

   只需要在括号中添加元素,并使用逗号隔开即可。

>>> tuple('Hello,world!')#通过tuple将序列转换为元组,用法和list一样
>>>tup1 = ('Google', 'Runoob', 1997, 2000);
>>> tup2 = (1, 2, 3, 4, 5 ); 
>>> tup3 = "a", "b", 12345, 54321, 'hello!'; # 不需要括号也可以 
>>> type(tup3) <class 'tuple'>
>>> tup4 = ();    #创建空元组

     元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可能有或没有括号, 不过括号通常是必须的(如果元组是更大的表达式的一部分)。 

注意:元组中只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:

>>>tup1 = (50) 
>>> type(tup1) # 不加逗号,类型为整型 
<class 'int'>

2、访问元组

元组可以使用下标索引来访问元组中的值:

tup1 = ('Google', 'Runoob', 1997, 2000,3,7) 
print ("tup1[0]: ", tup1[0]) 
print ("tup1[2:4]: ", tup1[2:4])
print("tup1[0][3]:",tup1[0][3])    

以上实例输出结果:

tup1[0]:  Google
tup1[2:4]:  (1997, 2000)  #含左不含右
tup1[0][3]:g
Python 表达式结果描述
tup1[2]1997读取第三个元素
tup1[-2]3反向读取;读取倒数第二个元素
tup1[1:]('Runoob', 1997, 2000,3,7)截取元素,从第二个开始后的所有元素。

3、修改元组

元组中的元素值是不允许修改的,但我们可以对元组进行连接组合;若元组的元素是列表,则可改列表中的元素:

>>> test=('a','b',['A','B'])
>>> print(test)
('a', 'b', ['A', 'B'])
>>> test[2][0]='x'
>>> test[2][1]='y'
>>> test
('a', 'b', ['x', 'y'])

      这里看似元素中的元素改变了,可是仔细分析下,元组中的第三个元素是一个列表。改变的是列表中的值,元组所指的这个元素列表并没有改变,需要注意这点!这就涉及到Python中的可变对象和不可变对象,像list这样的就是可变对象,tuple便是不可变对象。 

tup1 = (12, 34.56); 
tup2 = ('abc', 'xyz') 
tup3 = tup1 + tup2; print (tup3)# 创建一个新的元组
tup4=tup1*2 #输出(12, 34.56,12, 34.56)
tup5=tip1[1,-1]    #输出12 
tup1[0] = 100 # 修改元组元素操作是非法的。

以上实例输出结果:(12, 34.56, 'abc', 'xyz')

4、删除元组

元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组。

5、元组运算符

元组之间可以使用 + 号和 * 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。元组运算符与列表完全相同。

6、元组内置函数

  • len(tuple)   计算元组元素个数。
  • max(tuple)返回元组中元素最大值。
  • min(tuple)返回元组中元素最小值。
  • tuple(seq)将列表转换为元组。

五、字典dict

    字典是另一种可变容器模型,且可存储任意类型对象。序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。理解字典的最佳方式是把它看做无序的键=>值对集合。在同一个字典之内,关键字必须是互不相同。

    字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据。python对key进行哈希函数运算,根据计算的结果决定value的存储地址,所以字典是无序存储的,且key必须是可哈希的。可哈希表示key必须是不可变类型,如:数字、字符串、只含不可变类型元素的元组(1,2,3,’abc’)。所谓哈希表不过就是一个定长数组,元素找位置,遇到哈希冲突则利用 hash 算法解决找另一个位置,如果数组长度不够用则进行扩容,然后不断地循环反复。

  • 字典中的数据必须以键值对的形式出现
  • 键不可重复,值可重复,键若重复字典中只会记该键对应的最后一个值
  • 字典中键(key)是不可变的,为不可变对象,不能进行修改;而值(value)是可以修改的,可以是任何对象
  • 在dict中是根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了
  • dict中的元素是无序的,不可以采用分片。

1、字典的创建

字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号{}中 :

dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}

dict2 = { 'abc': 123, 98.6: 37 }

2、访问

访问字典里的值,把相应的键放入到方括号中

dict = {'Name': 'Runoob', 'Age': 7, 'Class': 'First'}
 
print ("name", dict['Name'])
print ("age", dict['Age'])

以上实例输出结果:
name:  Runoob
age:  7

3、增删改查

>>> tel = {'jack': 8, 'sape': 4139}
>>> tel['guido'] = 4127           #增添键值对
>>>tel['jack'] = 4098               # 修改值
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}

>>> tel['jack']
4098

>>> del tel['sape']    #删除键值对
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}

>>> list(tel.keys())
['irv', 'guido', 'jack']
>>> sorted(tel.keys())
['guido', 'irv', 'jack']

>>> 'guido' in tel
True
>>> 'jack' not in tel
False

4、字典内置函数&方法

1、len(dict) 计算字典元素个数,即键的总数。

2、keys() 方法返回一个可迭代对象,可以使用 list() 来转换为列表。

3、 values() 方法返回一个迭代器,可以使用 list() 来转换为列表,列表为字典中的所有值。

4、 items() 方法,以列表返回可遍历的(键, 值) 元组数组。

dict = {'Name': 'Runoob', 'Age': 7}
>>> list(dict.keys())             # 转换为列表
>>> list(dict.values())
['Name', 'Age']
['Runoob', 7]

5、pop(key[,default]) 删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。

6、get(key, default=None)方法(值不存在时返回NULL,也可指定返回的值):   dict[vote]=dict.get(vote,0)+1

dict = {'Name': 'Runoob', 'Age': 7}
print ("Value : %s" %  dict.items())

>>>Value : dict_items([('Age', 7), ('Name', 'Runoob')])

 python中的字典是无序的,因为它是按照hash来存储的,但是python中有个模块collections,里面自带了一个子类OrderedDict,实现了对字典对象中元素的排序。

import collections
print "Regular dictionary"
d={}
d['a']='A'
d['b']='B'
d['c']='C'
for k,v in d.items():
    print k,v

print "\nOrder dictionary"
d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'
d1['1'] = '1'
d1['2'] = '2'
for k,v in d1.items():
    print k,v

输出:
Regular dictionary
a A
c C
b B

Order dictionary
a A
b B
c C
1 1
2 2

使用OrderedDict会根据放入元素的先后顺序进行排序。所以输出的值是排好序的。OrderedDict对象的字典对象,如果其顺序不同那么Python也会把他们当做是两个不同的对象

六、集合set

    集合是一个无序不重复元素的集,集合是由哈希表实现的。基本功能包括关系测试和消除重复元素。集合里面的每个元素必须是不可变的数据类型,是可以hash的。

可以用大括号{ } 创建集合。注意:如果要创建一个空集合,你必须用 set() 而不是 {} ;后者创建一个空的字典:

>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)                      # 删除重复的
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket                 # 检测成员
True
>>> 'crabgrass' in basket
False

>>> # 以下演示了两个集合的操作
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # a 中唯一的字母
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # 在 a 中的字母,但不在 b 中
{'r', 'd', 'b'}
>>> a | b                              # 在 a 或 b 中的字母
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # 在 a 和 b 中都有的字母
{'a', 'c'}
>>> a ^ b                              # 在 a 或 b 中的字母,但不同时在 a 和 b 中
{'r', 'd', 'b', 'm', 'z', 'l'}
集合也支持推导式:

>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
{'r', 'd'}
  • 添加元素x到集合s                                                                            s.add( x )
  • 将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。        s.remove( x )
  • 计算集合 s 元素个数。                                                                     len(s)
  • 判断元素 x 是否在集合 s 中,存在返回 True,不存在返回 False。x in s

from :https://www.runoob.com/python3/python3-data-structure.html

         

 


版权声明:本文为qq_30815237原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。