Python--函数对象@命名空间与作用域@包函数@装饰器@迭代器@内置函数
一、函数对象
函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性。
那到底什么是第一类对象(First-Class Object)呢?
在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量、可以作为元素添加到集合对象中、可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的。
1.函数身为一个对象,拥有对象模型的三个通用属性:id、类型、和值。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def foo():
print('from foo')
foo() print(id(foo))
print(type(foo))
print(foo)
输出
from foo
4406808360
<class 'function'>
<function foo at 0x106aa8f28>
2.函数可以被引用,即函数可以赋值给一个变量
还可以把该函数赋值给更多的变量,唯一变化的是该函数对象的引用数不断地增加,本质上这些变量最终指向的都是同一个函数对象。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
def foo():
print('from foo') foo()
func=foo #引用,赋值
print(foo)
print(func)
func()
输出
from foo
<function foo at 0x10eed8f28>
<function foo at 0x10eed8f28>
from foo
3.函数可以当做参数传递
def foo():
print('from foo') def bar(func):
print(func)
func() bar(foo)
输出
<function foo at 0x1047eff28>
from foo
4.函数可以作返回值
函数接受一个或多个函数作为输入或者函数输出(返回)的值是函数时,我们称这样的函数为高阶函数
def foo():
print('from foo') def bar(func):
return func f=bar(foo) print(f) f()
输出
<function foo at 0x107f29f28>
from foo
5.函数可以当作容器类型的元素
容器对象(list、dict、set等)中可以存放任何对象,包括整数、字符串,函数也可以作存放到容器对象中
def foo():
print('from foo')
dic={'func':foo} foo() print(dic['func']) dic['func']()
输出
from foo
<function foo at 0x10997ef28>
from foo
6.函数还可以嵌套
函数嵌套的定义
def f1(): def f2():
print('from f2')
def f3():
print('from f3')
f3()
f2() f1()
输出
from f2
from f3
二、命名空间与作用域
命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值
1.命名空间的定义
name='egon' #定义变量 def func(): #定义函数
pass class Foo: #定义类
pass
2.命名空间的分类
- 1.内置名称空间: 随着python解释器的启动而产生,包括异常类型、内置函数和特殊方法,可以代码中任意地方调用
print(sum)
print(max)
print(min) print(max([1,2,3])) import builtins
for i in dir(builtins): #打印所有的内置函数
print(i)
输出
- 2.全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间
x=1 #全局命名空间 def func():
money=2000 #非全局
x=2
print('func')
print(x)
print(func)
func()
- 3.局部名称空间:调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束解绑定
x=10000 #全局
def func():
x=1 #局部
def f1():
pass
3.作用域
命名空间的可见性就是作用域
- 1. 全局作用域:内置名称空间,全局名称空间
- 2. 局部作用域:局部名称空间
名字的查找顺序:局部名称空间---》全局名层空间---》内置名称空间
查看全局作用域内的名字:gloabls()
查看局部作用域内的名字:locals()
全局作用域的名字:全局有效,在任何位置都能被访问到,除非del删掉,否则会一直存活到文件执行完毕
局部作用域的名字:局部有效,只能在局部范围调用,只在函数调用时才有效,调用结束就失效
x=1000
def func(y):
x=2
print(locals())
print(globals()) func(1)
输出
{'y': 1, 'x': 2}
{'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10c436c88>, '__package__': None, '__cached__': None, '__file__': '/Users/hexin/PycharmProjects/py3/day4/2.py', 'func': <function func at 0x10c3c9f28>, '__builtins__': <module 'builtins' (built-in)>, '__spec__': None, '__doc__': None, 'time': <module 'time' (built-in)>, '__name__': '__main__', 'x': 1000}
四、闭包函数
简单来说,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。
闭包函数须满足以下条件:
1. 定义在内部函数;
2. 包含对外部作用域而非全局作用域的引用;
例
def f1():
x = 1
def f2():
print(x)
return f2 f=f1()
print(f) x=100
f()
print(x)
输出
<function f1.<locals>.f2 at 0x107714400>
1
100
闭包应用
from urllib.request import urlopen def index(url):
def get():
return urlopen(url).read()
return get oldboy=index('http://crm.oldboyedu.com') print(oldboy().decode('utf-8'))
输出
五、装饰器
1.定义
装饰器:修饰别人的工具,修饰添加功能,工具指的是函数
装饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用对象
2.为什么要用装饰器?
开放封闭原则:对修改是封闭的,对扩展是开放的
装饰器就是为了在不修改被装饰对象的源代码以及调用方式的前提下,为其添加新功能
3.装饰器的实现
装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”
直接看示意图,其中 a 为与装饰器 @a 对应的函数, b 为装饰器修饰的函数,装饰器@a的作用是:
简而言之:@a 就是将 b 传递给 a(),并返回新的 b = a(b)
例如
def a(name):#与装饰器对应的函数
name() @a#装饰器 b = a(b)
def b():#被装饰函数
print('zjl')
输出
zjl
解析过程是这样子的:
1.python 解释器发现@a,就去调用与其对应的函数( a 函数)
2.a 函数调用前要指定一个参数,传入的就是@a下面修饰的函数,也就是 b()
3.a() 函数执行,调用 b(),b() 打印“zjl”
5.装饰器的应用
import time def timmer(func):
def wrapper():
start_time=time.time()
func() #index()
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return wrapper @timmer #index=timmer(index)
def index():
time.sleep(1)
print('welcome to index') index()
输出
welcome to index
run time is 1.005241870880127
例子
login_user={'user':None,'status':False}
def auth(func):
def wrapper(*args,**kwargs):
if login_user['user'] and login_user['status']:
res=func(*args,**kwargs)
return res
else:
name=input('请输入用户名: ')
password=input('请输入密码: ')
if name == 'zjl' and password == '':
login_user['user']='hexin'
login_user['status']=True
print('\033[45mlogin successful\033[0m')
res=func(*args,**kwargs)
return res
else:
print('\033[45mlogin err\033[0m')
return wrapper @auth #index=auth(index)
def index():
print('welcome to index page') @auth #home=auth(home)
def home(name):
print('%s welcome to home page' %name) index()
home('zjl')
输出
请输入用户名: zjl
请输入密码: 123
login err
请输入用户名: zjl
请输入密码: 123
login successful
hexin welcome to home page
补充:
装饰器的基本框架:
def timer(func):
def wrapper():
func()
return wrapper
带参数
def timer(func):
def wrapper(*args,**kwargs):
func(*args,**kwargs)
return wrapper
六、可迭代对象和迭代器
1.迭代的概念
上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
注:循环不是迭代
while True: #只满足重复,因而不是迭代
print('====>')
2.可迭代的对象
内置__iter__方法的,都是可迭代的对象。
list是可迭代对象,dict是可迭代对象,set也是可迭代对象。
[1,2].__iter__()
'hello'.__iter__()
(1,2).__iter__() {'a':1,'b':2}.__iter__()
{1,2,3}.__iter__()
例如:
x = [1, 2, 3]
y = iter(x)
z = iter(x)
print(next(y))
print(next(y))
print(next(z))
print(type(x))
print(type(y))
输出
1
2
1
<class 'list'>
<class 'list_iterator'>
这里x
是一个可迭代对象,y
和z
是两个独立的迭代器,迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。
迭代器有一种具体的迭代器类型,比如list_iterator
,set_iterator
。可迭代对象实现了__iter__
方法,该方法返回一个迭代器对象。
3.迭代器
- 1.为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。
- 2.迭代器定义:
迭代器:可迭代对象执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法
它是一个带状态的对象,他能在你调用next()
方法的时候返回容器中的下一个值,任何实现了__iter__
和__next__()
方法的对象都是迭代器,__iter__
返回迭代器自身,__next__
返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常
- 3.迭代器的实现
例:
i=[1,2,3].__iter__() print(i) #迭代器 print(i.__next__())
print(i.__next__())
print(i.__next__())
#print(i.__next__()) #抛出异常:StopIteration
输出
<list_iterator object at 0x1019c3eb8>
1
2
3
每次调用next()
方法的时候做两件事:
- 为下一次调用
next()
方法修改状态 - 为当前这次调用生成返回结果
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
- 4.如何判断迭代器对象和可迭代对象
from collections import Iterable,Iterator
'abc'.__iter__()
().__iter__()
[].__iter__()
{'a':1}.__iter__()
{1,2}.__iter__() f=open('a.txt','w')
f.__iter__()
#判断是否为可迭代对象,以下都是
print(isinstance('abc',Iterable))
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({'a':1},Iterable))
print(isinstance({1,2},Iterable))
print(isinstance(f,Iterable))
#判断是否为迭代器,只有文件是
print(isinstance('abc',Iterator))
print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({'a':1},Iterator))
print(isinstance({1,2},Iterator))
print(isinstance(f,Iterator))
输出
True
True
True
True
True
True
False
False
False
False
False
True
可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象
迭代器:有__iter__
和__next__()
方法
注:对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
- 5.迭代器的优点和缺点
优点:
1.提供了一种不依赖下标的迭代方式
2.就跌迭代器本身来说,更节省内存
缺点:
1. 无法获取迭代器对象的长度
2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退
七、内置函数
简单来说就是python3本身就自带的函数。
- abs(x)
abs()返回一个数字的绝对值。如果给出复数,返回值就是该复数的模
print(abs(-1100))
输出:1100
- all()
如果iterable的所有元素不为0、''、False或者iterable为空,all(iterable)返回True,否则返回False;
print(all(['a', 'b', 'c', 'd'])) #列表list,元素都不为空或0
print(all(['a', 'b', '', 'd'])) #列表list,存在一个为空的元素
print(all([0,1,2,3])) #列表list,存在一个为0的元素
print(all(('a', 'b', 'c', 'd'))) #元组tuple,元素都不为空或0
print(all(('a', 'b', '', 'd'))) #元组tuple,存在一个为空的元素
print(all((0,1,2,3))) #元组tuple,存在一个为0的元素
print(all([])) # 空列表
print(all(())) # 空元组
True
False
False
True
False
False
True
True
注意:空元组、空列表返回值为True,这里要特别注意
- any()
如果所有元素中有一个值非0、''或False,那么结果就为True,当iterable所有的值都是0、''或False时,那么结果为False,
print(any(['a', 'b', 'c', 'd'])) #列表list,元素都不为空或0
print(any(['a', 'b', '', 'd'])) #列表list,存在一个为空的元素
print(any([0,1,2,3])) #列表list,存在一个为0的元素
print(any(('a', 'b', 'c', 'd'))) #元组tuple,元素都不为空或0
print(any(('a', 'b', '', 'd'))) #元组tuple,存在一个为空的元素
print(any((0,1,2,3))) #元组tuple,存在一个为0的元素
print(any([])) # 空列表
print(any(())) # 空元组
True
True
True
True
True
True
False
False
- ascii()
调用对象的__repr__()方法,获得该方法的返回值.
print(ascii([1,2,3,1,22,123])) #[1, 2, 3, 1, 22, 123]
- bin()
三个函数功能为:将十进制数分别转换为2进制。
print(bin(10)) #0b1010
- bool()
测试一个对象是True还是False.
print(bool([])) #False
- bytes()
将一个字符串转换成字节类型
s="apple"
v=bytes(s,encoding="utf-8")
print(v) #b'apple'
- callable(object)
callable()函数用于测试对象是否可调用,如果可以则返回1(真);否则返回0(假)。可调用对象包括函数、方法、代码对象、类和已经定义了 调用 方法的类实例。
a = '123'
print(callable(a)) #False
- chr(i)
chr()函数返回ASCII码对应的字符串。
print(chr(65)) #A
- complex(real[,imaginary])
complex()函数可把字符串或数字转换为复数。
print(complex(2,1)) #(2+1j)
- delattr()
删除对象的属性
- dict()
创建数据字典
print(dict()) #{}
- dir()
不带参数时返回当前范围内的变量,方法和定义的类型列表,带参数时返回参数的属性,方法列表
print(dir())
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'time']
- divmod(x,y)
divmod(x,y)函数完成除法运算,返回商和余数。
print(divmod(10,3)) #(3, 1)
- enumerate()
返回一个可以枚举的对象,该对象的next()方法将返回一个元组
s = ["a","b","c"]
for i ,v in enumerate(s,1):
print(i,v)
1 a
2 b
3 c
- eval()
将字符串str当成有效的表达式来求值并返回计算结果
s = "1 + 3 +5"
print(eval(s)) #9
- exec()
执行字符串或complie方法编译过的字符串,没有返回值
- float(x)
float()函数把一个数字或字符串转换成浮点数。
print(float("12")) #12.0
- format()
格式化输出字符串
print("i am {0},age{1}".format("tom",18))
i am tom,age18
- frozenset()
创建一个不可修改的集合
set
和
frozenset
最本质的区别是前者是可变的,后者是不可变的。当集合对象会被改变时(例如删除,添加元素),只能使用
set
,
一般来说使用fronzet的地方都可以使用
set
。
参数iterable:可迭代对象。
- globals()
返回一个描述当前全局变量的字典
a = "apple"
print(globals())
{'__package__': None, '__file__': '/Users/hexin/PycharmProjects/py3/day4/2.py', '__name__': '__main__', 'a': 'apple', 'time': <module 'time' (built-in)>, '__cached__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10bd73c88>, '__builtins__': <module 'builtins' (built-in)>, '__spec__': None, '__doc__': None}
- hash()
哈希值hash
(
object
)注意:可哈希的即不可变数据类型,不可哈希即可变数据类型
如果对象
object
为哈希表类型,返回对象
object
的哈希值。哈希值为整数,在字典查找中,哈希值用于快递比价字典的键。
两个数值如果相等,则哈希值也相等。
- help()
返回对象的帮助文档
调用内建的帮助系统,如果不包含参数,交互式帮助系统将在控制台启动。如果参数为字串,则可以是模块,类,方法等名称,并且帮助页面将会在控制台打印。参数也可以为任意对象
- hex(x)
hex()函数可把整数转换成十六进制数。
print(hex(12)) #0xc
- id()
返回对象的内存地址
a = "apple"
print(id(a)) #4562197840
- input()
获取用户输入内容
- int(x[,base])
int()函数把数字和字符串转换成一个整数,base为可选的基数。
- iter()
返回一个iterator对象。
- len()函数返回字符串和序列的长度。
print(len('aa')) #2
- list(x)
list()函数可将序列对象转换成列表。
print(list("hello world"))
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
- locals()
打印当前可用的局部变量的字典
- max(x[,y,z...])
max()函数返回给定参数的最大值,参数可以为序列。
print(max(1,2,3,4)) #4
- min(x[,y,z...])
min()函数返回给定参数的最小值,参数可以为序列。
print(min(1,2,3,4)) #1
- next()
返回一个可迭代数据结构(如列表)中的下一项
- object()
获取一个新的,无特性(geatureless)对象。
Object
是所有类的基类。它提供的方法将在所有的类型实例中共享。
- oct(x)
oct()函数可把给出的整数转换成八进制数。
print(oct(12)) #0o14
- ord(x)
ord()函数返回一个字符串参数的ASCII码或Unicode值。
print(ord("a")) #97
- open()
打开文件open
(filename [, mode [, bufsize]])
打开一个文件,返回一个
file
对象。 如果文件无法打开,将处罚IOError异常
- pow(x,y[,z])
pow()函数返回以x为底,y为指数的幂。如果给出z值,该函数就计算x的y次幂值被z取模的值。
print(pow(2,5)) #32
print(pow(2,5,3)) #2
- range([lower,]stop[,step])
range()函数可按参数生成连续的有序整数列表。
print(range(1,10,2)) #range(1, 10, 2)
- repr()
将任意值转换为字符串,供计时器读取的形式
- reversed()
反转,逆序对象
- round(x[,n])
round()函数返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。
print(round(5.9)) #6
- set()
将对象转换成集合
- slice()
切片功能
s = ["a","b""c","d"]
print(slice(1,3,s))
slice(1, 3, ['a', 'bc', 'd'])
- sorted()
排序
列表排序,按数轴方向排,高阶函数,以绝对值大小排序,字符串排序,按照ASCII的大小排序,如果需要排序的是一个元组,则需要使用参数key,也就是关键字。反向排序,reserve=True
- str(obj)
str()函数把对象转换成可打印字符串。
print(str(4)) #4
- sum()
求和
- tuple(x)
tuple()函数把序列对象转换成tuple。
print(tuple("hello world"))
('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd')
- type(obj)
type()函数可返回对象的数据类型。
print(type('123'))
print(type(1))
<class 'str'>
<class 'int'>
- vars()
本函数是实现返回对象object的属性和属性值的字典对象。如果默认不输入参数,就打印当前调用位置的属性和属性值,相当于locals()的功能。如果有参数输入,就只打印这个参数相应的属性和属性值。
print(vars()) #{'__name__': '__main__', '__spec__': None, '__package__': None, '__builtins__': <module 'builtins' (built-in)>, 'time': <module 'time' (built-in)>, '__cached__': None, '__doc__': None, '__file__': '/Users/hexin/PycharmProjects/py3/day4/2.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10e5f3c88>}
print(vars(time))
- zip()
将对象逐一配对
s='helloo'
l=[1,2,3,4,5] z=zip(s,l)
print(z)
for i in z:
print(i)
<zip object at 0x1051d1608>
('h', 1)
('e', 2)
('l', 3)
('l', 4)
('o', 5)
Python--函数对象@命名空间与作用域@包函数@装饰器@迭代器@内置函数的更多相关文章
- 【Python 函数对象 命名空间与作用域 闭包函数 装饰器 迭代器 内置函数】
一.函数对象 函数(Function)作为程序语言中不可或缺的一部分,但函数作为第一类对象(First-Class Object)却是 Python 函数的一大特性. 那到底什么是第一类对象(Firs ...
- 万恶之源 - Python装饰器及内置函数
装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...
- Python装饰器及内置函数
装饰器 听名字应该知道这是一个装饰的东西,我们今天就来讲解一下装饰器,有的铁子们应该听说,有的没有听说过.没有关系我告诉你们这是一个很神奇的东西 这个有多神奇呢? 我们先来复习一下闭包 def fun ...
- Python装饰器、内置函数之金兰契友
装饰器:装饰器的实质就是一个闭包,而闭包又是嵌套函数的一种.所以也可以理解装饰器是一种特殊的函数.因为程序一般都遵守开放封闭原则,软件在设计初期不可能把所有情况都想到,所以一般软件都支持功能上的扩展, ...
- python笔记5:装饰器、内置函数、json
装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象. 先看简单例子: def run(): time.sleep(1 ...
- python 之 面向对象(多态性、装饰器方法 内置函数补充)
7.6 多态性 1 什么是多态性 多态指的是同一种事物多种形态,在程序中用继承可以表现出多态.多态性:可以在不用考虑对象具体类型的前提下而直接使用对象下的方法 2.为什要用多态 用基类创建一套统一的规 ...
- 文成小盆友python-num4 装饰器,内置函数
一 .python 内置函数补充 chr() -- 返回所给参数对应的 ASCII 对应的字符,与ord()相反 # -*- coding:utf-8 -*- # Author:wencheng.z ...
- day0318装饰器和内置函数
一.装饰器 1.装饰器: 解释:装饰器的本事就是一个函数,不改动主代码的情况下,增加新功能.返回值也是一个函数对象. 2.装饰器工作过程 import time def func(): print(' ...
- python12--字符串的比较 函数的默认值的细节 三元表达式 函数对象 名称空间 作用域 列表与字典的推导式 四则运算 函数的嵌套
复习 1.字符串的比较; 2.函数的参数; ******实参与形参的分类: 3.函数的嵌套调用: # 字符串的比较# -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 ...
随机推荐
- shell 流程控制语句
case语句 case $变量名 in "值1") 如果变量的值等于值1,则执行程序1 ;; "值2") 如果变量的值等于值2,则执行程序2 ;; ...
- ActiveMQ的发布者/订阅者模型示例
ActiveMQ的发布者/订阅者模型入门示例 (1)下载安装activemq,启动activeMQ. 详细步骤参考博客:http://www.cnblogs.com/DFX339/p/9050878. ...
- caffe中全卷积层和全连接层训练参数如何确定
今天来仔细讲一下卷基层和全连接层训练参数个数如何确定的问题.我们以Mnist为例,首先贴出网络配置文件: name: "LeNet" layer { name: "mni ...
- vue-6-事件处理
<div id="example-2"> <button v-on:click="greet">Greet</button> ...
- 二:通过VirtualBox+Vagrant创建一个centos的虚拟机:
官网安装VirtualBox及Vagrant. 下载centos7,添加到vagrant中. http://e-proxy.yfb.sunline.cn/download/vagrant/centos ...
- [Linux]Linux下rsync服务器和客户端配置
一.rsync简介 Rsync(remote sync)是UNIX及类UNIX平台下一款神奇的数据镜像备份软件,它不像FTP或其他文件传输服务那样需要进行全备份,Rsync可以根据数据的变化进行差异( ...
- Java基础知识补充
基础知识总结: 学习了一段时间,重新看了孤傲苍狼的博客,对一些知识有了新的理解. unicode: 全球的文字放到计算机里面表示全是0和1,Unicode是统一了全世界国家文字的一种编码方式,用这样的 ...
- linux 下ftp几种上传和下载方式
1. ftp自动登录批量下载文件. 复制代码代码如下: #####从ftp服务器上的/home/data 到 本地的/home/databackup#####!/bin/bashftp -n<& ...
- L255
If a farmer wishes to succeed, he must try to keep a wide gap between his consumption and his produc ...
- python socket 编程之三:长连接、短连接以及心跳(转药师Aric的文章)
长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...