python基础之函数,递归,内置函数
一、数学定义的函数与python中的函数
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域
例如y=2*x。
python中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中函数定义方法: def test(x):
"The function definitions"
x+=1
return x def:定义函数的关键字
test:函数名
():内可定义形参
"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值 调用运行:可以带参数也可以不带
方法:函数名()
test()
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。
二 为何使用函数
1.代码重用
2.保持一致性,易维护
3.可扩展性
三 函数和过程
过程定义:过程就是简单特殊没有返回值的函数。
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01():
pass def test02():
return 0 def test03():
return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'} t1=test01()
t2=test02()
t3=test03() print 'from test01 return is [%s]: ' %type(t1),t1
print 'from test02 return is [%s]: ' %type(t2),t2
print 'from test03 return is [%s]: ' %type(t3),t3
结果:
from test01 return is [<class 'NoneType'>]: None
from test02 return is [<class 'int'>]: 0
from test03 return is [<class 'tuple'>]: (0, 10, 'hello', ['alex', 'lb'], {'WuDaLang': 'lb'})
四 函数参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
4.默认参数
5.参数组
def test(x, *args):
print(x)
print(args)
test(1)
test(1, 2, 3, 4, 5)
test(1, {'name': 'alex'})
test(1, ['x', 'y', 'z'])
test(1, *['x', 'y', 'z'])
test(1, *{'name': 'alex'})
结果为:
def test(x, **kwargs):
print(x)
print(kwargs)
test(1, y = 2, z = 3)
test(1, y = 2, z = 3, z = 4) #会报错,一个参数不能传两个值
test(1, **{'y': 1, 'z': 23})
结果为:
def test(x, *args, **kwargs):
print(x)
print(args)
print(kwargs, kwargs.get('y')) test(1, 1, 3, 44, 2, x = 1, y = 2, z = 3) #报错
test(1, 1, 3, 44, 2, y = 2, z = 3)
test(1, *[1, 3, 44, 2], **{'y': 1})
结果为:
五 局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
name='lhf' def change_name():
print('我的名字',name) change_name() def change_name():
name='帅了一笔'
print('我的名字',name) change_name()
print(name) def change_name():
global name
name='帅了一笔'
print('我的名字',name) change_name()
print(name)
1、
name = 'lgh' def change_name():
#global name
name = 'shuaileyibi'
print('change_name', name) change_name()
print(name) ————————————————
结果为:
change_name shuaileyibi
lgh
name = 'lgh' def change_name():
global name
name = 'shuaileyibi'
print('change_name', name) change_name()
print(name) ————————————————————
结果为:
change_name shuaileyibi
shuaileyibi
2、
name = ['lgh', 'zs'] def change_name():
#global name
name.append('shuaileyibi')
print('change_name', name) change_name()
print(name) ——————————————————————
结果为:
change_name ['lgh', 'zs', 'shuaileyibi']
['lgh', 'zs', 'shuaileyibi']
name = ['lgh', 'zs'] def change_name():
global name
name.append('shuaileyibi')
print('change_name', name) change_name()
print(name) ——————————————————————————
结果为:
change_name ['lgh', 'zs', 'shuaileyibi']
['lgh', 'zs', 'shuaileyibi']
3、如果函数的内部无global关键字
--有声明局部变量
name = ['lgh', 'zs'] def change_name():
name = 'io'
print('change_name', name) change_name()
print(name) ————————————————
结果为:
change_name io
['lgh', 'zs']
--无声明局部变量
def change_name():
name.append('shuaileyibi')
print('change_name', name) change_name()
print(name) ——————————————————
结果为:
change_name ['lgh', 'zs', 'shuaileyibi']
['lgh', 'zs', 'shuaileyibi']
总结:
优先读取局部变量,只能读取全局变量,无法对全局变量重新赋值;
但是对于可变类型,可以对内部元素进行操作
4、如果函数中有global关键字,变量本质上就是全局变量,可读取可赋值
--有声明局部变量
name = ['lgh', 'zs'] def change_name():
global name
name = 'io'
print('change_name', name) change_name()
print(name) ————————————————
结果为:
change_name io
io
错误示例
name = ['lgh', 'zs'] def change_name():
name = 'io'
global name
print('change_name', name) change_name()
print(name) ——————————————
报错
SyntaxError: name 'name' is assigned to before global declaration
--无声明局部变量
name = ['lgh', 'zs'] def change_name():
global name
name.append('shuaileyibi')
print('change_name', name) change_name()
print(name) ————————————————
结果为:
change_name ['lgh', 'zs', 'shuaileyibi']
['lgh', 'zs', 'shuaileyibi']
一般规定:
###### 全局变量变量名大写
###### 局部变量变量名小写
5、一些例子
#1
name = 'gy' def wh():
name = 'cz'
def wwh():
global name
name = 'lj' wwh()
print(name)
print(name)
wh()
print(name) ————————————————
结果为:
gy
cz
lj
#2
name = 'gy' def wh():
name = 'cz'
def wwh():
nonlocal name #nonlocal,指代上一级的变量
name = 'lj' wwh()
print(name) print(name)
wh()
print(name) ————————————————————
结果为:
gy
lj
gy
#3
name = 'gy' def wh():
nonlocal name
name = 'lj'
print('name1', name) print(name)
wh()
print(name) ——————————————————
报错:
SyntaxError: no binding for nonlocal 'name' found
六 前向引用之'函数即变量'
def action():
print('in the action')
logger() action() ————————————
结果为:
NameError: name 'logger' is not defined
def logger():
print('in the logger') def action():
print('in the action')
logger() action() ————————————————
结果为:
in the action
in the logger
def action():
print('in the action')
logger() def logger():
print('in the logger') action() ————————————————
结果为:
in the action
in the logger
七 嵌套函数和作用域
1、嵌套函数:在函数中再定义函数,或者函数的返回值是另一个函数的函数名
#1
name = 'alex'
def foo():
name = 'lhf'
def bar():
print(name)
return bar foo() ————————————
结果为:
lhf
#2
def test1():
print('in the test1') def test():
print('in the test')
return test1
#3
name = 'alex' def foo():
name = 'lhf'
def bar():
#name = 'wpq'
print(name)
return bar
#4
name='alex' def foo():
name='lhf'
def bar():
name='wupeiqi'
def tt():
print(name)
return tt
return bar
八 递归调用
在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身,则称递归调用。
def calc(n):
print(n)
if int(n/2) == 0:
return n
return calc(int(n/2)) calc(10) ————————————————
结果为:
10
5
2
1
import time person_list = ['alex', 'wpq', 'yh', 'lhf', 'zsc']
def ask_way(person_list):
print('-'*60)
if len(person_list) == 0:
return print('根本没人知道') person = person_list.pop(0)
if person == 'lhf':
return '%s说:我知道。' %person print('hi [%s], 敢问路在何方' %person)
print('%s回答道:我不知道,我帮你问问%s...' %(person, person_list))
time.sleep(1)
res = ask_way(person_list)
print('%s 问的结果是:%res' %(person, res))
return res res = ask_way(person_list)
print(res) ————————————————————————————
结果是:
------------------------------------------------------------
hi [alex], 敢问路在何方
alex回答道:我不知道,我帮你问问['wpq', 'yh', 'lhf', 'zsc']...
------------------------------------------------------------
hi [wpq], 敢问路在何方
wpq回答道:我不知道,我帮你问问['yh', 'lhf', 'zsc']...
------------------------------------------------------------
hi [yh], 敢问路在何方
yh回答道:我不知道,我帮你问问['lhf', 'zsc']...
------------------------------------------------------------
yh 问的结果是:'lhf说:我知道。'es
wpq 问的结果是:'lhf说:我知道。'es
alex 问的结果是:'lhf说:我知道。'es
lhf说:我知道。
递归问路
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
九 匿名函数
匿名函数就是不需要显式的指定函数
def calc(x):
return x + 1 res = calc(10)
print(res) ——————————————————
结果为:
11
lambda匿名函数:
func = lambda x: x + 1 print(func(10)) ——————————————————————
结果为:
11
name = 'alex'
#1函数式
def change_name(x):
return x + '_sb' res = change_name(name)
print(res) ————————————————————
结果为:
alex_sb #2匿名函数式
f = lambda x: x+'_sb'
res = f(name)
print('匿名函数的运行结果', res)
————————————————————
结果为:
匿名函数的运行结果 alex_sb
多个参数的匿名函数:
func = lambda x, y, z: x + y + z print(func(1, 2, 3)) ——————————————————
结果为:
6
f = lambda x, y, z: (x + 1, y + 1, z + 1) #得自己加括号
print(f(2,3,4)) ——————————————————
结果为:
(3, 4, 5)
匿名函数主要是和其它函数搭配使用,如下:
dic={'k1':10,'k2':100,'k3':30} print(max(dic)) #取的是键的最大值
print(dic[max(dic,key=lambda k:dic[k])]) #传入匿名函数方法,取值的最大值的键,进而得到最大值 ————————————————————
结果为:
k3
100
十 函数式编程
函数式编程又是面向过程的编程方式:
函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的函数,一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。
例如:
用户登录流程:前端接收处理用户请求-》将用户信息传给逻辑层,逻辑词处理用户信息-》将用户信息写入数据库
验证用户登录流程:数据库查询/处理用户信息-》交给逻辑层,逻辑层处理用户信息-》用户信息交给前端,前端显示用户信息
十一 高阶函数
满足以下两种之一的就是高阶函数:
1、把函数当做参数传给另外一个函数,即函数的传入参数是一个函数名
def foo(n):
print(n) def bar(name):
print('my name is %s' %name) foo(bar('alex')) ————————————————————
结果为:
my name is alex
None
2、返回值中包含函数,即函数的返回值是一个函数名
#1
def bar():
print('from bar') def foo():
print('from foo')
return bar n = foo()
n() ——————————————————————
结果为:
from foo
from bar
#2
def handle():
print('from handle')
return handle h = handle()
h() ————————————————————
结果为:
from handle
from handle
#3
def test1():
print('from test1')
def test2():
print('from test2')
return test1() #把test1的运行结果作为返回值 h = test2() ——————————————————
结果为:
from test2
from test1
十二 函数补充——map,reduce,filter和format字符串格式化应用
1、map函数
#1 自定制初级map函数(逻辑函数写死的方法):给列表里的每个元素取乘方
num_l = [1, 2, 10, 5, 3, 7] def map_test(array):
ret = []
for i in array:
ret.append(i**2)
return ret ret = map_test(num_l)
print(ret) ————————————————
结果为:
[1, 4, 100, 25, 9, 49]
#2 自定制map函数(逻辑函数可变的方法)
num_l = [1, 2, 10, 5, 3, 7] #lambda x: x + 1
def add_one(x):
return x + 1 #lambda x: x - 1
def sub_one(x):
return x - 1 def map_test(func, array):
ret = []
for i in array:
res = func(i)
ret.append(res)
return ret print(map_test(add_one, num_l))
print(map_test(lambda x: x + 1, num_l)) print(map_test(sub_one, num_l))
print(map_test(lambda x: x - 1, num_l)) ——————————————————
结果为:
[2, 3, 11, 6, 4, 8]
[2, 3, 11, 6, 4, 8]
[0, 1, 9, 4, 2, 6]
[0, 1, 9, 4, 2, 6]
#3 map函数——map(func, iter)
num_l = [1, 2, 10, 5, 3, 7] #lambda x: x + 1
def add_one(x):
return x + 1 #lambda x: x - 1
def sub_one(x):
return x - 10 #传入匿名函数
res = map(lambda x: x + 1, num_l)
print('内置函数map, 处理结果', res) #map的结果是一个可迭代对象
print(list(res)) ————————————————————
结果为:
内置函数map, 处理结果 <map object at 0x000000B8DCFD8DD8>
[2, 3, 11, 6, 4, 8] ============================================================ #传入有名函数
print('传的是有名函数', list(map(sub_one, num_l))) ————————————————————
结果为:
传的是有名函数 [0, 1, 9, 4, 2, 6]
可迭代对象均可运用map
msg = 'lhf'
print(list(map(lambda x: x.upper(), msg))) ——————————————————————
结果为:
['L', 'H', 'F']
2、filter函数
#1 自定制初级filter函数(逻辑函数写死的方法):筛选列表里的符合条件的元素
movie_people = ['sb_alex', 'sb_wpq', 'lhf', 'sb_yh'] def filter_test(array):
ret = []
for p in array:
if not p.startswith('sb'):
ret.append(p)
return ret res = filter_test(movie_people)
print(res) ——————————————————————
结果为:
['lhf']
#2 自定制filter函数(逻辑函数可变的方法)
movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] def sb_show(n):
return n.endswith('sb') def filter_test(func, array):
ret = []
for p in array:
if not func(p):
ret.append(p)
return ret res = filter_test(sb_show, movie_people)
print(res) ——————————————————————
结果为:
['lhf']
#3 filter函数——filter(func, iter)
movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] def sb_show(n):
return n.endswith('sb')
#--->lambda n: n.endswith('sb') #传入有名函数
res = filter(sb_show, movie_people)
print(res)
print(list(res)) ————————————————————————
结果为:
<filter object at 0x000000AB22CEAE80>
['alex_sb', 'wpq_sb', 'yh_sb'] ==================================== #传入匿名函数
movie_people = ['alex_sb', 'wpq_sb', 'lhf', 'yh_sb'] print(list(filter(lambda n: not n.endswith('sb'), movie_people))) ————————————————————————
结果为:
['lhf']
一个应用:在列表中筛选出年龄<=18的条目:
people = [
{'name': 'alex', 'age': 1000},
{'name': 'wpq', 'age': 10000},
{'name': 'yh', 'age': 9000},
{'name': 'lhf', 'age': 18}
]
print(list(filter(lambda p: p['age']<=18, people))) ——————————————————————————
结果为:
[{'name': 'lhf', 'age': 18}]
3、reduce函数
#1 自定制初级reduce函数(逻辑函数写死的方法):处理一个序列,然后把序列进行合并操作
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(array):
res = 0
for num in array:
res += num
return res print(reduce_test(num_l)) ——————————————————
结果为:
121
#2 自定制reduce函数(逻辑函数可变的方法)
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(func, array):
res = array.pop(0)
for num in array:
res = func(res, num)
return res print(reduce_test(lambda x, y: x * y, num_l)) ————————————————————————
结果为:
72000
可传入初始值的自定制reduce函数:
num_l = [1, 2, 3, 4, 5, 6, 100] def reduce_test(func, array, init=None):
if init is None:
res = array.pop(0)
else:
res = init
for num in array:
res = func(res, num)
return res print(reduce_test(lambda x, y: x * y, num_l, 100)) ————————————————————————————
结果为:
7200000
#3 reduce函数——filter(func, iter, init=None)
from functools import reduce num_l = [1, 2, 3, 4, 5, 6, 100]
print(reduce(lambda x, y: x + y, num_l, 1)) ————————————————————————
结果为:
122
小结:
map: 处理序列中的每个元素,得到的结果是一个‘列表’(迭代器),该‘列表’元素个数及位置与原来一样
filter: 遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下来
reduce: 处理一个序列,然后把序列进行合并操作
4、format字符串格式化——'{}'.format()
#1 按顺序传值,不一一对应报错
tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')
print(tpl) ————————————————————————————
结果为:
i am seven, age 18, alex
#2 传入数字代表匹配的位置
tpl = "i am {2}, age {1}, {0}".format("seven", 18, 'alex') print(tpl) ————————————————————————————
结果为:
i am alex, age 18, seven ===================================== tpl = "i am {1}, age {1}".format("seven", 18, 'alex') print(tpl) ————————————————————————————
结果为:
i am 18, age 18
#3 传入'键值对'来进行匹配
1、通过"="的形式传值
tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18) print(tpl) ——————————————————————
结果为:
i am seven, age 18, really seven ======================================================================================== 2、通过字典的形式传值
tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18}) print(tpl) ——————————————————————
结果为:
i am seven, age 18, really seven
#4 {}中可以添加一些特殊格式
tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) print(tpl) ————————————————————————
结果为:
numbers: 1111,17,15,f,F, 1587.623000%
5、字符串应用之"%"
#1 %s可以代指字符串及其他数据结构
#2 %d只能代表数字格式
#3 %f代表浮点型,可以限制小数位数(%.2f等)
打印百分比
#4 通过键值对传值——如 “%(name)s,%(age)d” % {'name': 'alex', 'age': 18}
msg = 'i am \033[43:1m%(name)+10s\033[0m my hobby is alex' % {'name': 'lh'} print(msg)
改变字体颜色?
补充:字符串拼接——print函数中的sep参数
python基础之函数,递归,内置函数的更多相关文章
- python基础12_匿名_内置函数
一个二分查找的示例: # 二分查找 示例 data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35, 36, ...
- Python基础(七)内置函数
今天来介绍一下Python解释器包含的一系列的内置函数,下面表格按字母顺序列出了内置函数: 下面就一一介绍一下内置函数的用法: 1.abs() 返回一个数值的绝对值,可以是整数或浮点数等. 1 2 3 ...
- python基础之 装饰器,内置函数
1.闭包回顾 在学习装饰器之前,可以先复习一下什么是闭包? 在嵌套函数内部的函数可以使用外部变量(非全局变量)叫做闭包! def wrapper(): money =10 def inner(num) ...
- Python基础(十一)--内置函数
内置函数 数学类 abs():绝对值 round():四舍五入 >>> round(1.3747,1) 1.4 sum():求和 >>> sum({1:'dj',2 ...
- 【python基础语法】常用内置函数、关键字、方法和之间的区别(小结)
''' 关键字: False:bool数据类型 True:bool数据类型 None:表示数据的内容为空 and:逻辑运算符:与 or:逻辑运算符:或 not:逻辑运算符:非 in:身份运算符,判断变 ...
- 【python基础】常用的内置函数
python基础之内置函数 参考: http://www.runoob.com/python/python-built-in-functions.html -zip() zip函数接受任意多个(包括0 ...
- python基础学习1-类相关内置函数
#!/usr/bin/env python # -*- coding:utf-8 -*- #===issubclass(class,classinfo) 检查class是否是classinfo类的子类 ...
- Python基础(六)-内置函数
map().filter().reduce() map(func,iterator) --> filter(func,iterator) --> reduce(func,iterato ...
- python基础知识15---三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
阅读目录 一 三元表达式.列表推导式.生成器表达式 二 递归与二分法 三 匿名函数 四 内置函数 五 阶段性练习 一. 三元表达式.列表推导式.生成器表达式 1 三元表达式 name=input('姓 ...
- python之三元表达式、列表推导、生成器表达式、递归、匿名函数、内置函数
目录 一 三元表达式 二 列表推到 三 生成器表达式 四 递归 五 匿名函数 六 内置函数 一.三元表达式 def max(x,y): return x if x>y else y print( ...
随机推荐
- Docker的安装和操作(虚拟机+linux系统)
1.简介 Docker是一个开源的应用容器引擎:是一个轻量级容器技术: Docker支持将软件编译成一个镜像:然后在镜像中各种软件做好配置,将镜像发布出去,其他使用者可以直接使用这个镜像: 运行中的这 ...
- 3ds Max File Format (Part 1: The outer file format; OLE2)
The 3ds Max file format, not too much documentation to be found about it. There are some hints here ...
- 理解Login函数
_LoginPartial.cshtml文件 其中 <li>@Html.ActionLink("Log in", "Login", "Ac ...
- bugku sql2
sql注入2 200 http://123.206.87.240:8007/web2/ 全都tm过滤了绝望吗? 提示 !,!=,=,+,-,^,%
- java-Timestamp
java获取取得Timestamp类型的当前系统时间格式:2010-11-04 16:19:42 方法1: Timestampd = new Timestamp(System.currentTimeM ...
- codeforces 1269D. Domino for Young (二分图证明/结论题)
链接:https://codeforces.com/contest/1269/problem/D 题意:给一个不规则的网格,在上面放置多米诺骨牌,多米诺骨牌长度要么是1x2,要么是2x1大小,问最多放 ...
- http请求常见错误状态码
一.HTTP 错误 400 400 请求出错 由于语法格式有误,服务器无法理解此请求.不作修改,客户程序就无法重复此请求. 原因:(调用方接口方法的实参和服务器接口方法的形参不一致) 1.前端提交数据 ...
- Vue - 自定义组件双向绑定
前言 无论在任何的语言或框架中,我们都提倡代码的复用性.对于Vue来说也是如此,相同的代码逻辑会被封装成组件,除了复用之外,更重要的是统一管理提高开发效率.我真就接手过一个项目,多个页面都会用到的列表 ...
- BeautifulSoup的基本使用
一.将一段文档传入BeautifulSoup的构造方法,得到一个文档的对象: from bs4 import BeautifulSoup Soup = BeautifulSoup(html_doc) ...
- 生产环境设置mysql主从复制
Slave服务器的版本要等于或者高于master服务器 现在的实例是在mysql 5.7上的主从配置 a) master服务器的my.cnf配置,server_id 推荐用IP的后两位数字 [mysq ...