Python语法基础

Python语法基础

本文说的python都是指python3,python3语言最大的特点是:

  1. 面向对象编程: Python是一种面向对象的语言,它支持面向对象编程的所有特性,如封装、继承、多态等。
  2. 动态类型: 在 Python中,变量的类型不需要事先声明,Python解释器会自动确定它们的类型,python变量的类型随着赋值不同而随时变化,这与C、JAVA等强类型语言有很大的不同,python容器的元素类型也可以各不相同,这也是与强类型语言的显著差别
  3. 解释型语言: Python是一种解释型语言,它不需要编译器将代码转换成机器码。这使得 Python 3 更加灵活和易于开发和调试。
  4. 在基本语法上与C、JAVA相近,但它有很多脚本语言的特征

基本语法

编码

默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件的第一行或第二行(指定的解释器之后)指定不同的编码:

# -*- coding: gbk -*-

标识符规则

1、标识符由大小写字母、数字、下划线组成,在Python 3中,非-ASCII 标识符也是允许的。

2、第一个字符必须是字母表中字母或下划线 _ ,不能以数字开头。

3、标识符是区分大小写的。

4、以下划线开头的标识符是有特殊意义的:

   1)以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用"from xxx import *"导入;

   2)以双下划线开头的(__foo)代表类的私有成员;

   3)以双下划线开头和结尾的(__foo__)代表python里特殊方法专用的标识,如__init__()代表类的构造函数。

5、Python 可以同一行显示多条语句,方法是用分号 ;

缩进规则

  1. python里面不用{}来分割类、函数、以及其他逻辑判断代码块,而是使用缩进和冒号来区别代码块之间的层次关系。
  2. 缩进的空白数量是可变的,但是所有代码块语句必须包含相同的缩进空白数量
  3. 多行语句:用反斜杠来连接,如果包含[],{},()括号就不需要用多行连接符
  4. 可以同一行书写多条语句,但需要用分号进行分割

以下代码最后一行语句缩进数的空格数不一致,会导致运行错误:

if True:
    print ("Answer")
    print ("True")
else:
    print ("Answer")
  print ("False")    # 缩进不一致,会导致运行错误

注释

  1. 单行注释用#开头
  2. 通过成对的三个单引号进行块注释
'''
这是多行注释
'''

空行

  1. 函数之间或类的方法之间用空行分隔,表示一段新的代码的开始,类和函数入口之间也用一行空行分隔,以突出函数入口的开始
  2. 空行不是python语法的一部分,书写时不插入空行,python解释器也不会运行出错,但是空行的作用在于分隔两段不同功能或含义的代码,便于日后代码的维护或重构

关键字

>>> help('keywords')
Here is a list of the Python keywords.  Enter any keyword to get more help.

False               class               from                or
None                continue            global              pass
True                def                 if                  raise
and                 del                 import              return
as                  elif                in                  try
assert              else                is                  while
async               except              lambda              with
await               finally             nonlocal            yield
break               for                 not                 

import与from...import

  • 在 python 用 import 或者 from...import 来导入相应的模块。
  • 将整个模块(somemodule)导入,格式为: import somemodule,引用导入模块的函数或变量时,需要在前面加上模块名somemodule.,如果模块名太长,可以使用别名
  • 将整个模块(somemodule)导入,并且指定别名,格式为: import somemodule as aliasname,引用导入模块的函数或变量时,可以使用别名aliasname.
  • 从某个模块中导入某个函数或变量,格式为: from somemodule import somefunction,可以直接使用该函数和变量,不需要在前面带上模块名
  • 也从某个模块中导入多个函数和变量,中间用逗号分隔,格式为: from somemodule import firstfunc, secondfunc, thirdfunc
  • 也可以将某个模块中的全部函数和变量导入,一般不建议这么操作,格式为: from somemodule import *
import sys
print('================Python import mode==========================')
print ('命令行参数为:')
for i in sys.argv:
    print (i)
print ('\n python 路径为',sys.path)
from sys import argv,path  #  导入特定的成员
 
print('================python from import===================================')
print('path:',path) # 因为已经导入path成员,所以此处引用时不需要加sys.path
# 导入sys整个模块,并指定别名为s
import sys as s
# 使用s模块别名作为前缀来访问模块中的成员
print(s.argv[0])
# 导入sys、os两个模块,并为sys指定别名s,为os指定别名o
import sys as s,os as o
# 使用模块别名作为前缀来访问模块中的成员
print(s.argv[0])
print(o.sep)

# 导入sys模块的argv成员,并为其指定别名v
from sys import argv as v
# 使用导入成员(并指定别名)的语法,直接使用成员的别名访问
print(v[0])

# 导入sys模块的argv,winver成员,并为其指定别名v、wv
from sys import argv as v, winver as wv
# 使用导入成员(并指定别名)的语法,直接使用成员的别名访问
print(v[0])
print(wv)

 在使用 from...import 语法时,可以一次导入指定模块内的所有成员(此方式不推荐),例如如下程序:

#导入sys 棋块内的所有成员
from sys import *
#使用导入成员的语法,直接使用成员的别名访问
print(argv[0])
print(winver)

 上面代码一次导入了 sys 模块中的所有成员,这样程序即可通过成员名来使用该模块内的所有成员。该程序的输出结果和前面程序的输出结果完全相同。

需要说明的是,一般不推荐使用“from 模块 import”这种语法导入指定模块内的所有成员,因为它存在潜在的风险。比如同时导入 module1 和 module2 内的所有成员,假如这两个模块内都有一个 foo() 函数,调用foo函数时就不知道是调用的module1还是module2的函数了。

但如果换成下面import方式,调用这两个模块中的 foo() 函数就非常清晰了:

import module1
import module2 as m2
#使用模块module1 的模块名作为前缀调用foo()函数
module1.foo()
#使用module2 的模块别名作为前缀调用foo()函数
m2.foo()

或者:

#导入module1 中的foo 成员,并指定其别名为foo1
from module1 import foo as fool
#导入module2 中的foo 成员,并指定其别名为foo2
from module2 import foo as foo2

foo1() #调用module1 中的foo()函数
foo2() #调用module2 中的foo()函数

命令行参数

很多程序可以执行一些操作来查看一些基本信息,Python可以使用-h参数查看各参数帮助信息:

$ python -h
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Options and arguments (and corresponding environment variables):
-c cmd : program passed in as string (terminates option list)
-d     : debug output from parser (also PYTHONDEBUG=x)
-E     : ignore environment variables (such as PYTHONPATH)
-h     : print this help message and exit

[ etc. ]

基础类型

Numbers(数字)

  1. int(有符号整型):通常被称为是整型或整数,是正或负整数,不带小数点。Python3 整型是没有限制大小的,可以当作 Long 类型使用,所以 Python3 没有 Python2 的 Long 类型。布尔(bool)是整型的子类型.
  2. float(浮点型):浮点型由整数部分与小数部分组成,浮点型也可以使用科学计数法表示,最大浮点数为1.7976931348623157e+308。
  3. complex(复数):复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示, 复数的实部a和虚部b都是浮点型。

Bool(布尔类型)

布尔型的两个取值分别是True和Fasle,注意大小写的差异。

String(字符串)

python的字符串和C、Java等的字符串类似,通过引号括起来。

详细的字符串学习参见Python字符串

List(列表)

List列表是一种有序的集合(和数学中的数组类似),其中的元素可以随时添加和删除,是 Python 中最基本的数据结构之一。

定义使用中括号 [ ] ,里面元素可以是任意类型,也包括列表本身,也可以是字典、元组等。

Tuple(元组)

有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改。

元组使用小括号,列表使用方括号。元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可

Dictionary(字典)

字典(Dictionary)是一种映射结构的数据类型,由无序的“键-值对”组成。字典的键必须是不可改变的类型,如:字符串,数字,tuple;值可以为任何python数据类型。用 { } 标识。

字典语法:dictionary={key1:value1,key2:value2.............}

Key是字典中的键,value是对应的值

字典必须用大括号{},key与对应的value用“:”连接,中间用“,”断开。

key必须是数值、字符串、元组三种类型,其特点就是不可变,key在字典中是唯一的

Set(集合)

在Python中,Set 是一个无序的不重复元素序列。我们可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。

type()和isinstance()

type()函数获得变量、常量的类型

使用isinstance()可以检查变量所指的对象类型,如:

a, b, c = 1, 2, 'abc'
print(a, b, c)  # 1 2 abc
# 查看变量所指的对象类型
print(type(a))   # 
print(type(b))   # 
print(type(c))   # 

print(isinstance(a, int))  # True

注意点:isinstancetype的区别在于

  1. type()不会认为子类是一种父类类型
  2. isinstance()会认为子类是一种父类类型

变量

  1. 变量不用显示的声明类型,都是由解释器对类型做出的推断,同一个变量的类型也不固定,根据它的值而变化。
>>> x=2
>>> print(x)
2
>>> x="test"
>>> print(x)
test
>>>

  1. 变量不需要生命周期管理,每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建
  2. 可以多变量赋值
# 以下实例,创建一个整型对象,值为1,从后向前赋值,三个变量被赋予相同的数值
a = b = c = 1
# 以下实例,两个整型对象1和2的分配给变量a和b,字符串对象‘abc’分配给变量c
a, b, c = 1, 2, 'abc'
print(a, b, c)  # 1 2 abc

  1. 可以使用del语句删除一些对象引用,例如:
del a
del b,c

运算符

算术运算

算符

描述

实例

+

 - 两个对象相加

a + b 输出结果 31

-

 - 得到负数或是一个数减去另一个数

a - b 输出结果 -11

*

 - 两个数相乘或是返回一个被重复若干次的字符串

a * b 输出结果 210

/

 - x 除以 y

b / a 输出结果 2.1

%

取模 - 返回除法的余数

b % a 输出结果 1

**

 - 返回xy次幂

a**b 1021次方

//

取整除 - 往小的方向取整数

>>> 9//2

4

>>> -9//2

-5

比较运算符

运算符

描述

实例

==

等于 - 比较对象是否相等

(a == b) 返回 False

!=

不等于 - 比较两个对象是否不相等

(a != b) 返回 True

>

大于 - 返回x是否大于y

(a > b) 返回 False

<

小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量TrueFalse等价。注意,这些变量名的大写。

(a < b) 返回 True

>=

大于等于 - 返回x是否大于等于y

(a >= b) 返回 False

<=

小于等于 - 返回x是否小于等于y

(a <= b) 返回 True

赋值运算符

运算符

描述

实例

=

简单的赋值运算符

c = a + b  a + b 的运算结果赋值为 c

+=

加法赋值运算符

c += a 等效于 c = c + a

-=

减法赋值运算符

c -= a 等效于 c = c - a

*=

乘法赋值运算符

c *= a 等效于 c = c * a

/=

除法赋值运算符

c /= a 等效于 c = c / a

%=

取模赋值运算符

c %= a 等效于 c = c % a

**=

幂赋值运算符

c **= a 等效于 c = c ** a

//=

取整除赋值运算符

c //= a 等效于 c = c // a

:=

海象运算符,可在表达式内部为变量赋值。Python3.8 版本新增运算符

在这个示例中,赋值表达式可以避免调用 len() 两次:

if (n := len(a)) > 10:

    print(f"List is too long ({n} elements, expected <= 10)")

位运算符

运算符

描述

实例

&

按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0

(a & b) 输出结果 12 ,二进制解释: 0000 1100

|

按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1

(a | b) 输出结果 61 ,二进制解释:0011 1101

^

按位异或运算符:当两对应的二进位相异时,结果为1

(a ^ b) 输出结果 49 ,二进制解释:0011 0001

~

按位取反运算符:对数据的每个二进制位取反,即把1变为0,0变为1~x 类似于 -x-1

(~a ) 输出结果 -61 ,二进制解释:1100 0011 在一个有符号二进制数的补码形式。

<<

左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0

a << 2 输出结果 240 ,二进制解释: 1111 0000

>>

右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数

a >> 2 输出结果 15 ,二进制解释: 0000 1111

逻辑运算符

运算符

逻辑表达式

描述

实例

and

x and y

布尔"" - 如果 x  Falsex and y 返回 x 的值,否则返回 y 的计算值。

(a and b) 返回 20

or

x or y

布尔"" - 如果 x  True,它返回 x 的值,否则它返回 y 的计算值。

(a or b) 返回 10

not

not x

布尔"" - 如果 x  True,返回False 。如果 x  False,它返回True

not(a and b) 返回 False

成员运算符

运算符

描述

实例

in

如果在指定的序列中找到值返回 True,否则返回False

 y 序列中 , 如果 x  y 序列中返回 True

not in

如果在指定的序列中没有找到值返回 True,否则返回 False

不在 y 序列中 , 如果 x 不在 y 序列中返回 True

身份运算符

运算符

描述

实例

is

is 是判断两个标识符是不是引用自一个对象

x is y类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False

is not

is not 是判断两个标识符是不是引用自不同对象

x is not y  类似 id(x) != id(y)。如果引用的不是同一个对象则返回结果 True,否则返回 False

注: id() 函数用于获取对象内存地址。

运算符优先级

运算符

描述

(expressions...),

[expressions...]{key: value...}{expressions...}

圆括号的表达式

x[index]x[index:index]x(arguments...)x.attribute

读取,切片,调用,属性引用

await x

await 表达式

**

乘方(指数)

+x-x~x

正,负,按位非 NOT

*@///%

乘,矩阵乘,除,整除,取余

+-

加和减

<<>>

移位

&

按位与 AND

^

按位异或 XOR

|

按位或 OR

in,not in, is,is not, <, <=, >, >=, !=, ==

比较运算,包括成员检测和标识号检测

not x

逻辑非 NOT

and

逻辑与 AND

or

逻辑或 OR

if -- else

条件表达式

lambda

lambda 表达式

:=

赋值表达式

类型转换

隐式类型转换规则

  1. 较低数据精度类型(整数)就会转换为较高数据精度类型(浮点数)以避免数据丢失,数据类型的精度由低到高依次是:bool int float complex。
  2. 当将一个任意类型的值与字符串拼接时,Python也会自动将其转换为字符串类型

显示类型转换

  1. int(x) 将x转换为一个整数。
  2. float(x) 将x转换到一个浮点数。
  3. complex(x) 将x转换到一个复数,实数部分为 x,虚数部分为 0。
  4. complex(x, y) 将 x 和 y 转换到一个复数,实数部分为 x,虚数部分为 y。x 和 y 是数字表达式。
  5. bool(x):将x转换为一个bool值,非空为True,空为Fasle。
  6. str(x):将对象转化为适于人阅读的形式。
  7. chr(x): 用一个范围在 range(256)内的(就是0~255)整数作参数,返回对应的 ASCII 字符
  8. ord(x):chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常
  9. hex(x): 用于将10进制整数转换成16进制,以字符串形式表示
  10. oct(x): 将一个整数转换成 8 进制字符串。Python3.x 版本的 8 进制以 0o 作为前缀表示

条件控制

if-else

#形式1
if 判断条件:
    语句块

#形式2
if 判断条件:
    语句块1
else:
    语句块2

#形式3
if 判断条件1:
    语句块1
elif 判断条件2:
    语句块2
…
elif 判断条件n:
    语句块n
else :
    语句块n+1

#嵌套
if 判断条件1:
    if 判断条件2:
        语句块1
    else:
        语句块2
else:
    if 判断条件3:
        语句块3
    else:
        语句块4

条件表达式

python里的条件表达式与C、JAVA中的不同,它是条件控制语句的简写方式,语法格式为:

条件成立时执行的语句 if condition else 条件不成立时执行的语句

#例如:

small=a if ay else y+1
print(z)

'''
输出
3
'''

还可以写成嵌套的形式:

#条件表达式的方法
#例子:根据输入分数,输出评分等级:0-60分为D,60-80分为C,80-90分为B,90-100分为A
a=int(input("请输入你的分数:"))
level=('D' if 0<=a<60 else
       'C' if 60<=a<80 else
       'B' if 80<=a<90 else
       'A' if 90<=a<=100 else
       "请输入0-100以内的数")
print(level)

#常规方法
a=int(input("请输入你的分数:"))
if 0<=a<60:
    print('D')
elif 60<=a<80:
    print('C')
elif 80<=a<90:
    print('B')
elif 90<=a<100:
    print('A')
else:
    print('请输入0-100以内的数')

match-case

python没有switch-case语句,但在Python 3.10 增加了 match...case 的条件判断,不需要再使用一连串的 if-else 来判断了,使用上比switch-case更为强大

详细的学习参见match-case的使用

循环控制

在Python中,循环控制有两个:for循环、while循环。在学习这两个循环语句之前,先简单学习一下range函数。

range函数

Python3 range() 函数返回的是一个可迭代对象(类型是对象)

函数语法为:

range(stop)
range(start, stop[, step])

参数说明:

  • start: 计数从 start 开始。默认是从 0 开始。例如 range(5) 等价于 range(0, 5)
  • stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是 [0, 1, 2, 3, 4] 没有 5
  • step:步长,默认为 1。例如:range(0, 5) 等价于 range(0, 5, 1)

for循环

语法格式为

for iterating_var in sequence:
   statements

例子:

for letter in 'Python':     # 第一个实例
   print("当前字母: %s" % letter)
 
fruits = ['banana', 'apple',  'mango']
for fruit in fruits:        # 第二个实例
   print ('当前水果: %s'% fruit)
 
'''
当前字母: P
当前字母: y
当前字母: t
当前字母: h
当前字母: o
当前字母: n
当前水果: banana
当前水果: apple
当前水果: mango
'''

for...else循环

在for后还可以跟一个else的语句,for 中的语句和普通的没有区别,else 中的语句会在循环正常执行完(即 for 不是通过 break 跳出而中断的)的情况下执行

def forelse(num):
    for i in range(2, num):
        if num % i == 0:  # 确定第一个因子
            j = num / i  # 计算第二个因子
            print('%d 等于 %d * %d' % (num, i, j))
            break  # 跳出当前循环
    else:  # 循环的 else 部分
        print('%d 是一个质数' % num)

forelse(13)
forelse(8)

'''
13 是一个质数
8 等于 2 * 4
'''


while循环

在某条件下,循环执行某段程序,以处理需要重复处理的相同任务

while 判断条件(condition):
    执行语句(statements)

例子:

a = 1
while a < 10:
    print(f'{a=}')
    a += 2


'''
a=1
a=3
a=5
a=7
a=9
'''

while...else循环

与for...else循环一致,在不是break跳出来的情况下,都会执行的语句

def whileelse(num):
    i = 2
    while i < num:
        if num % i == 0:  # 确定第一个因子
            j = num / i  # 计算第二个因子
            print('%d 等于 %d * %d' % (num, i, j))
            break  # 跳出当前循环
        i += 1
    else:  # 循环的 else 部分
        print('%d 是一个质数' % num)
whileelse(13)
whileelse(8)

'''
13 是一个质数
8 等于 2 * 4

while表达式

while与if一样,也可以写成表达式的形式:

a = 0
while a < 10: a +=2
print(f'{a=}')

'''
a=10
'''

对于多行语句,也可以使用分号分隔开

a = 1
b = 2
while a < 10:  a += 1; b += 2
print(f'{a=}, {b=}')

'''
a=10, b=20
'''

控制语句

break语句

在语句块执行过程中终止循环,并且跳出整个循环

Python break语句,就像在C语言中,打破了最小封闭for或while循环。

break语句用来终止循环语句,即循环条件没有False条件或者序列还没被完全递归完,也会停止执行循环语句。

break语句用在while和for循环中。

如果您使用嵌套循环,break语句将停止执行最深层的循环,并开始执行下一行代码。


for letter in 'Python':     # 第一个实例
   if letter == 'h':
      break
   print '当前字母 :', letter
  
var = 10                    # 第二个实例
while var > 0:              
   print '当前变量值 :', var
   var = var -1
   if var == 5:   # 当变量 var 等于 5 时退出循环
      break
 
'''
当前字母 : P
当前字母 : y
当前字母 : t
当前变量值 : 10
当前变量值 : 9
当前变量值 : 8
当前变量值 : 7
当前变量值 : 6
'''

continue语句

Python continue 语句跳出本次循环,而break跳出整个循环。

continue 语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环。

continue语句用在while和for循环中。

for letter in 'Python':     # 第一个实例
   if letter == 'h':
      continue
   print '当前字母 :', letter
 
var = 10                    # 第二个实例
while var > 0:              
   var = var -1
   if var == 5:
      continue
   print '当前变量值 :', var

'''
当前字母 : P
当前字母 : y
当前字母 : t
当前字母 : o
当前字母 : n
当前变量值 : 9
当前变量值 : 8
当前变量值 : 7
当前变量值 : 6
当前变量值 : 4
当前变量值 : 3
当前变量值 : 2
当前变量值 : 1
当前变量值 : 0
'''

pass语句

Python pass 是空语句,是为了保持程序结构的完整性。

pass 不做任何事情,一般用做占位语句。

# 输出 Python 的每个字母
for letter in 'Python':
   if letter == 'h':
      pass
      print '这是 pass 块'
   print '当前字母 :', letter

'''
当前字母 : P
当前字母 : y
当前字母 : t
这是 pass 块
当前字母 : h
当前字母 : o
当前字母 : n
'''

基本输入输出

Python提供了 input() 内置函数从标准输入读入一行文本,默认的标准输入是键盘。

基本格式:

input([prompt])

接受一个标准输入数据,返回为 string 类型

str = input("请输入:");
print ("你输入的内容是: ", str)

'''
请输入:abcdef
你输入的内容是: abcdef
'''

print() 方法用于打印输出,最常见的一个函数。

基本格式为:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

参数说明:

  • objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
  • sep -- 用来间隔多个对象,默认值是一个空格。
  • end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。
  • file -- 要写入的文件对象。
  • flush -- 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。

>>>print(1)  
1  
>>> print("Hello World")  
Hello World  
 
>>> a = 1
>>> b = 'runoob'
>>> print(a,b)
1 runoob
 
>>> print("aaa""bbb")
aaabbb
>>> print("aaa","bbb")
aaa bbb
>>> 
 
>>> print("www","runoob","com",sep=".")  # 设置间隔符
www.runoob.com

自定义函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。自定义函数,基本有以下规则步骤:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数
  • 函数的第一行语句可以选择性地使用文档字符串(用于存放函数说明)
  • 函数内容以冒号起始,并且缩进
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。

基本的语法定义为:

def functionname( parameters ):
   "函数_文档字符串"
   function_suite
   return [expression]

你可能感兴趣的:(python,网络,开发语言)