今天这篇文章用白话串讲一下 Python 基础,力争让编程小白也能看懂。
0. 准备
Python 的出现让编程不再是程序员的专利。Python 大大降低了编程门槛,
现在有不少运营、产品、行政等岗位的朋友都在学习 Python,并用在工作中。
学编程就像是学外语一样,学外语是说给老外听的,学编程其实就是编给计算机听的。但编程的学习难度远低于学外语,有点初中数学的基础就足够了。
在正式进入教程之前,需要大家自行搭建好 Python 开发环境。为了节省篇幅,这里就不介绍了。
我用的是 Python3 的环境,编辑器用的是 PyCharm。
1. 变量
变量
是编程语言里最基础的概念。
变量
顾名思义就是可以变化的东西。大家肯定不是第一次接触它。在学数学的时候就学过自变量
和因变量
。
y = 1+x
这个函数,x
是自变量,y
是因变量,因为它俩的取值都是变化的,所以它俩都是变量
。
一个网站的代码可以不变,但内容却可以不断变化。这个道理就好比上面的函数,函数本身是不变的,但x和y可以千变万化。
这就是我们第一节学习变量的意义。
1.1 Hello, World!
Hello, World!
是学习任何一门编程语言的必经之路,下面是 Python 版的 Hello, World!
print('Hello, World!')
print
是个函数,它的作用是输出Hello, World
文本。
现在只需要知道函数可以提供某项特定的功能就可以了,后面会详细介绍。
此时还没有用到变量,下面我们就来定义一个。
1.2 定义变量
x = 'Hello, World'
print(x)
x
是定义的变量。
=
是赋值运算符,它的含义与数学里的定义不同。在数学中它叫等号,而在编程语言里它叫赋值。
数学里是从等号左边往右边看。而编程语言里是从右往左看,表示把等号右边的内容赋值给等号左边的变量。
x = 'Hello, World'
会把字符串Hello, World
赋值给变量x
。
执行print(x)
后,输出 Hello, World
。
下面我们来改变 x
的取值。
x = 'Hello, World'
print(x) # Hello, World
x = '渡码'
print(x) # 渡码
上述例子中,x
可以看做自变量
,print
是函数,print(x)
则是因变量
。这样是不是有点 y = 1 + x
的感觉了。
当然 Python 中并没有自变量
和因变量
的概念,这里只是用来帮助理解。
1.3 变量的类型
上面的例子中变量的取值都是文本类型,在 Python 中,用单引号('
)或者双引号("
)引用起来的部分就是文本,也叫做字符串(后面有介绍)。
Python 中,除了字符串类型,还有以下数据类型:
- 整型(
int
):对应数学中的整数,如:1,101 - 浮点型(
float
):对应数学中的小数,如:3.14 - 字符串型(
str
):以单引号或双引号括起来的任意文本,如'Hello, World'
和"渡码"
。 - 布尔型(
bool
):取值只有True
、False
两种,一般用于逻辑判断,后面有介绍。
x = 10
print(x)
x = 1.23
print(x)
x = True
print(x)
1.4 变量的命名
上面例子中,我们定义了一个变量,名称是x
。变量的名称也不能是随便定义的,就像我们的名字一样,不能胡乱起,得遵循一定的规则。
Python 中,变量命名规则如下:
- 变量名由字母、数字和下划线构成,数字不能开头
- 大小写敏感,如:大写的
A
和小写的a
是两个不同的变量 - 变量名不要跟Python语言的关键字冲突,某些单词被 Python 赋予特殊含义了,我们就不能再用了。举个形象的例子:毛主席的名字我们就不要再起了。
这几条规则,其实适用于大多数编程语言。
除了规则,还有一个规范大家在写 Python 代码时需要注意:
变量名一般小写,并且变量名由多个单词组成的时候,以下划线分隔
之所以说它是规范而不是规则,是因为你不遵守也不影响程序运行,然而会显得你的代码格外丑陋。
如:下面两个变量
my_name = '渡码' # 如何规范
mYnAmE = '渡码' # 不符合规范
这两行代码的好坏,高下立判。
在实际开发中肯定不是一个人写代码,所以遵循相同的规范可以减少大家的开发、维护成本。
1.5 变量互转
不同类型的变量是可以相互转化的。转化的方法如下:
int()
:将一个数值或字符串转换成整数float()
:将一个数值或字符串转换成浮点数str()
:将指定的对象转换成字符串形式bool()
:将指定对象转换成布尔型type()
:输出指定对象的类型
例子:
>>> x = '11'
>>> print(type(x))
<class 'str'>
>>>
>>> x = int(x)
>>> print(type(x))
<class 'int'>
>>>
>>> x = float(x)
>>> print(type(x))
<class 'float'>
>>>
>>> y = float('11.0')
>>> print(y)
11.0
>>> print(type(y))
<class 'float'>
2. 运算符
这节我们来学习 Python 中的运算符。
我们学数学的时候就学过运算符加、减、乘、除
,在 Python 中也是一样的。
2.1 算术运算符
运算符 | 描述 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取模 - 返回余数 |
** | 幂 |
// | 整除 - 取商的整数部分 |
>>> print(1 + 1)
2
>>> print(2 - 1)
1
>>> print(2 * 3)
6
>>> print(3 / 2)
1.5
>>> print(3 % 2)
1
>>> print(3 // 2)
1
>>> print(3 ** 2)
9
2.2 赋值运算符
运算符 | 描述 |
---|---|
= | 赋值运算符 |
+= | 加法赋值运算符,a += 1 等价于 a = a + 1 |
-= | 减法赋值运算符,a -= 1 等价于 a = a - 1 |
*= | 乘法赋值运算符,a *= 1 等价于 a = a + 1 |
/= | 除法赋值运算符,a /= 1 等价于 a = a / 1 |
%= | 取模赋值运算符,a %= 1 等价于 a = a % 1 |
**= | 幂赋值运算符,a = 1 等价于 a = a 1 |
//= | 整除赋值运算符,a //= 1 等价于 a = a // 1 |
赋值运算符=
在上一小节已经讲过了。
+=
、-=
、*=
、/=
、%=
、**=
、//=
是赋值运算符和算术运算组合而成的复合赋值运算符,表格里已经给出了它的等价代码。
例2.1:计算圆的周长和面积
输入半径,计算圆的半径和面积,圆周长公式:2*π*r
,面试公式:π*r^2
"""
半径计算圆的周长和面积
"""
radius = float(input('输入圆的半径: '))
perimeter = 2 * 3.1416 * radius
area = 3.1416 * radius ** 2
print('周长: %.2f' % perimeter)
print('面积: %.2f' % area)
input
是个函数,它接受用户的输入,并返回给程序。
2.3 比较运算符
运算符 | 描述 |
---|---|
== | 等于运算符 - 比较量两对象是否相等 |
!= | 不等运算符 - 比较量两对象是否不相等 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
比较的两个对象关系成立是返回 True
,否则返回 False
。
>>> a = 1
>>>
>>> print(a == 2)
False
>>> print(a != 2)
True
>>> print(a > 2)
False
>>> print(a < 2)
True
>>> print(a >= 2)
False
>>> print(a <= 2)
True
2.4 逻辑运算符
可以连接多个判断表达式,形成复杂的判断逻辑。
运算符 | 表达式 | 描述 |
---|---|---|
and | x and y | 与,x 和 y 都是 True,表达式返回 True,否则其中一个为 False,表达式返回 False |
or | x or y | 或,x 或 y 有一个为 True,表达式返回 True,否则都为 False,表达式返回 False |
not | not x | 非,若 x 为 True,返回 False |
逻辑运算符之间可以相互组合,如:x and y and z or e
。
下面代码判断变量a
是否在 2 - 10
的区间内
a = 4
print(a > 2 and a < 10)
运行代码输出 True
。
例2.2:判断闰年
输入年份,判断是否是闰年。闰年判断方法:能被4整除,但不能被100整除;或者能被 400 整除
。需要用到算术运算符
和逻辑运算符
"""
判断闰年
"""
year = int(input('输入年份: '))
is_leap = year % 4 == 0 and year % 100 != 0 or year % 400 == 0
print(is_leap)
其他运算符
其他运算符我们暂时列在这里,后面的章节再讲解,感兴趣的朋友可以先自行探索。
位运算符
运算符 | 描述 | |
---|---|---|
& | 按位与运算符 | |
按位或运算符 | ||
^ | 按位异或运算符 | |
~ | 按位取反运算符 | |
<< | 按位左移运算符 | |
>> | 按位右移运算符 |
按位
表示操作的是底层的二进制串,所以使用这些运算符需要了解二进制。
成员运算符
运算符 | 表达式 | 描述 |
---|---|---|
in | x in y | 若 x 在 y 中,返回 True,否则返回 False |
not in | x not in y | 若 x 不在 y 中,返回 True,否则返回 False |
身份运算符
运算符 | 表达式 | 描述 |
---|---|---|
is | x is y | 判断 x y 是否引用自相同对象 |
is not | x is not y | 判断 x y 是否不是引用自相同对象 |
3. 分支结构
上面写的 Python 代码都是顺序结构的,也就是说程序自上而下一条不落地执行。
只有顺序结构显然是不够的,比如:生活中我们会遇到这种情况。如果下雨,我们就在家吃饭,否则就出去吃饭。
在代码里也需要根据不同的情况执行不同的代码。
在 Python 代码里,可以表示为
if 下雨:
在家吃饭
else:
出去吃饭
这就是分支结构,在 Python 用 if ... else ...
结构来实现。其中,if
和else
是 Python 中的关键字。
当if
后面的表达式为 True
时,就会执行 if
下面的代码;否则就执行else
后面的代码。
3.1 单分支结构
例3.1 判断输入的数字是奇数还是偶数
"""
判断奇偶数
"""
in_x = int(input('输入整数:'))
if in_x % 2 == 0:
print('偶数')
else:
print('奇数')
if
语句后面可以有不止一行代码,在 Python 中使用缩进的方式来代表代码的层次结构,连续相同的缩进代码属于同一个代码块。也就是说,如果 if
语句后面想执行多行代码,它们必须保持相同的缩进,作为同一个代码块。
缩进一般使用的是 4 个空格。
3.2 多分支结构
有时候我们可能会遇到下面这种多分支的情况
如果 下雨,在家吃,否则如果阴天去附近吃,否则就去远处吃
在 Python 就可以使用if ... elif ... else ...
实现。
例3.2 输出成绩等级
输入成绩分数,输出分数对应的等级。
=90分得A,[80, 90) 得B,[70, 80)得C,[60, 70)得D,< 60得E
"""
输出成绩等级
"""
score = float(input('请输入成绩: '))
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
elif score >= 70:
grade = 'C'
elif score >= 60:
grade = 'D'
else:
grade = 'E'
print('成绩等级是:', grade)
在该例子中,我们可以看到 elif
语句可以写多个,有多少个判断分支,就可以写多少个 elif
语句。
3.3 分支嵌套
既然if
、elif
和else
语句后面需要写代码,那么自然也可以写分支结构的代码。如:
x = 10
if x > 4:
print('x 大于 4')
if x > 6:
print('x 大于 6')
else:
print('x 小于等于 6')
else:
print('x 小于等于 4')
if x > 2:
print('x 大于 2')
else:
print('x 小于等于 2')
这就是分支结构的嵌套,注意代码块的缩进,保持层次一致。
分支结构的意义在于根据不同情况做不同的判断,而不要一条道走到黑
4. 循环结构
上面我们学习的代码,只要程序启动一次,任意一行代码最多只能被执行1次。
这小节的学习的循环结构则可以让程序再次执行已经执行过的代码,并不断循环。
Python 中构造循环结构有两种语法,一种是 while
循环,另一种是 for-in
循环。
4.1 while 循环
while 循环写法与 if 分支类似,后面跟一个 bool
值条件表达式,程序会不断执行 while
代码块,直到条件表达式返回 False
。
i = 0
while i < 10:
print(i)
i += 1
print('end')
程序输出 0 ~ 9
10个数字。当 i < 10
时,while
代码块会执行,输出i
并让i
加1;当 i >= 10
时,while
代码块不会执行,程序会跳到 while
代码块后的代码执行print('end')
。
4.2 for-in
while
通过条件表达式来控制循环次数,for-in
通过 in
后面的数组控制循环的次数。
for i in range(0, 10):
print(i)
range是个函数,range(0, 10)
会生成 10 个元素的列表
:[0,1,2...9]。
for-in
语句会不断从列表
中取元素赋值给i
,然后执行 for-in
代码块,直到列表
内元素取完,则结束循环。
这种从头到尾扫描一次列表
的过程也叫做遍历
。
关于列表
,现在只需要直到它可以存储多个元素,后面会详细讲解它。
4.3 continue
当循环代码块中遇到 continue
语句,就不会执行后面代码,直接进入下一轮循环。
修改程序,当 i > 2 时,才输出 i。
for i in range(0, 10):
if i <= 2:
continue
print(i)
4.4 break
break
语句做得更绝,直接跳出 while 循环。
for i in range(0, 10):
if i > 2:
continue
print(i)
print('结束循环')
这里,for-in
代码块只输出了 0、1、2 便退出循环。
举一个 break
语句的应用场景:在用户登录时候,当用户输入的用户名和密码不对时,需要不断循环提示用户输入正确的用户名和密码,当用户输入正确后,就可以用 break
跳出循环,进入到登陆成功的页面。
循环结构跟分支结构一样,也是可以嵌套的。
例4.1 用户登录
实现用户登录过程。当输入用户名和密码都为 duma 时,登录成功。
"""
用户登录
"""
while True:
username = input('用户名: ')
password = input('密码: ')
if username == 'duma' and password == 'duma':
print('登录成功!')
break
else:
print('用户名或密码错误!')
循环结构的意义在于让程序循环重复执行代码,从而才可以代替人做一些重复性的劳动。
5. 函数和模块
函数
上面我们写的代码都是散装的,而函数可以把代码集合起来,形成一个个具有独立的功能的小模块。
Python中用def
定义函数。
# 实现一个一元一次方程
def f(x):
y = 1 + x
return 1 + x
a = f(1) # 2
为了便于理解,我们用 Python 函数实现了数学中y=1+x
一元一次方程。
从上面的例子可以看到一个函数的以下几个要素:
- 函数名 定义规则、规范跟变量一样
- 函数参数 位于函数名后面的小括号里,如上例中 x ,参数可以有多个也可以不填
- 函数体 函数名下面的代码块,它们的缩进应该是一样的。
- return语句 表示函数的返回值,可以省略
调用函数的方式是函数名(值1, 值2, ...)
。上例中,f(1)
表示调用函数f
并把数字1
传给参数x
。
多参数的函数
def login(user_name, password):
while True:
if user_name == 'duma' and password == '123456':
print("登录成功")
break
else:
print("用户名或密码错误")
login('duma', '123456')
调用多参数的函数时,括号里的值会从左至右依次传给函数的参数。
函数默认参数
定义函数的时候可以指定参数的默认值,当调用函数的时候,如果不给该参数传值,则函数会使用默认值。
def login(user_name, password='123456'):
while True:
if user_name == 'duma' and password == '123456':
print("登录成功")
break
else:
print("用户名或密码错误")
login('duma')
需要注意的是,如果某个参数使用了默认值,那么它右边的参数都需要指定默认值。
函数的意义在于将重复的代码封装起来,避免重复编写代码。
模块
目前我们编写的代码和函数都只能在当前文件调用,如果我们想调用其他文件里的某个函数怎么办。
这时候就需要用到模块的概念。前面说函数是将散装代码集合起来,那模块可以简单理解为将散装的函数集合起来。
在 user_module.py
定义一个用户登录验证的函数
def login(user_name, password):
while True:
if user_name == 'duma' and password == '123456':
print("登录成功")
break
else:
print("用户名或密码错误")
在 home.py
文件中就可以把user_module.py
作为一个模块来使用
import user_module
user_module.login('duma', '123456')
import
会导入user_module.py
的代码,通过user_module.函数名
就可以调用其中的函数。
导入模块的写法还可以用下面的方式
from user_module import login
login('duma', '123456')
# 给模块起别名
import user_module as um
um.login('duma', '123456')
模块意义在于将重复的功能(如:函数、类)封装起来,避免重复编写代码
6. 类和对象
之前我们学习了 Python 中的基本数据类型,你有没有想过要自己定义数据类型?
Python中可以用类来自定义数据类型。正所谓物以类聚,具有某些公共特征的元素就可以定义成一个类。
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def eat(self):
print(f'{self.name} 在吃饭...')
def introduct(self):
print(f'大家好,我是 {self.name},性别 {self.gender}')
上面我们定义了一个人类
,类名是Person
,包含两个变量name
和age
分别表示姓名和性别,在类中通过self.变量名
的方式访问类中的变量。
Person
类还包含两个函数,分别introduct
和eat
分别用来做自我介绍和吃饭。
经常跟类同时一个词是对象,类
只是一个抽象的概念,对象
才是鲜活的个例。如:人类只是一个概念,但你、我是一个个鲜活的个体。
对象通过类名()
方式创建,这个过程也叫实例化
。
下面我们用Person
类来实例化
一个程序中的人
。
p = Person('渡码', '男')
print(type(p))
# 输出:<class '__main__.Person'>
p.introduct()
# 输出:大家好,我是 渡码,性别 男
p.eat()
# 输出:渡码 在吃饭...
Person('渡码', '男')
会实例化一个类对象,程序会自动调用__int__
函数初始化,并把括号内的值传给__init__
函数的参数,__init__
执行结束后,就完成了对象的创建。
type
函数查看它的类型是<class '__main__.Person'>
,class
代表它是一个类,__main__.Person
是类的名称。
调用introduct
和 eat
函数完成相应的功能,因为这两个函数定义在类内部,所以需要通过类对象.函数名(参数)
的方式调用。
类中定义的函数除了默认会加slef
参数外,其他跟外部函数一样。虽然定义了self
参数,但调用的时候不需要给self
传值。
另外,类中定义的函数一般也被称为类方法
。
5. 数据结构之列表
后面的部分,主要介绍的下 Python 中的几个常用的数据结构列表
、元组
、字符串
、集合
和字典
。
因为它们是 Python 定义的类, 所以也叫内置类。
5.1 列表
列表
之前我们已经接触过了,它是一些元素的集合(元素可重复),Python中通过中括号 [] 来定义一个列表。
list1 = [1, 2, 3]
list2 = ['hello', 'world']
list3 = [1, 'hello', 2, 'world']
print(type(list3)) # <class 'list'>
为什么要定义列表? 当我们要存储100个数字时候,用数值类型变量需要定义100个,但列表只需定义1个。
使用类主要关注两方面内容,一个是它存储了哪些数据,另外一个是它能对存储的数据做什么操作。
上面我们已经看到了,列表
存储的就是可重复的元素集合,接下来我们看看它能提供什么操作
。
列表的生成
# 单列表
list1 = [1, 2, 3]
# 多列表的拼接
[1, 2] + [3, 4] #[1, 2, 3, 4]
# 列表的重复
[1, 2] * 3 #[1,2, 1,2, 1,2]
读取列表元素
通过 列表+中括号
的方式获取列表元素。中括号内填整数,该整数被称为数组的下标
,代表列表中第几个元素。
- 下标 >= 0代表从左到右的第几个,0代表第一个,所以下标要小于数组长度
- < 0 代表从右至左第几个,-1代表第一个
list1 = [1,2,3]
list1[0] # 1
list1[-1] # 3
获取子列表(切片)
与上面类似,通过 列表+中括号
的方式获取,格式为:list[i:j:k]
- i是起始下标,包含该元素,不填默认为0
- j代表结束下标,不包含该元素,不填默认为数组长度
- k代表步骤长,默认为1,不填步长时,第2个冒号可省略
list1 = [1,2,3,4]
print(list1[0:3]) # [1, 2, 3]
print(list1[:3]) # [1, 2, 3]
print(list1[2:]) # [3, 4]
print(list1[0:3:2]) # [1, 3]
添加元素
list1 = [1, 2]
# 列表尾部追加元素
list1.append(3) # [1, 2, 3]
# 向某个位置插入元素
# 第一个参数代表位置,第二个参数代表插入的元素
# 该位置之后元素右移
list1.insert(0, 10) # [10, 1, 2, 3]
删除元素
list1 = [1, 2, 3]
# 删除元素
list1.remove(3) #[1, 2]
# 删除某位置的元素
list1.pop(0) # [2]
其他操作
# 统计某个元素出现次数
list1 = [1, 3, 3]
list1.count(3) # 2
# 查找元素的下标,返回元素首次出现的下标。
# 第二个参数指定从哪个位置开始查找
list1=[1, 2, 2]
print(list1.index(1)) # 0
print(list1.index(2, 2)) # 2
# 反转列表
list1=[1,2,3]
list1.reverse() #[3, 2, 1]
# 列表排序
list1=[3,2,1]
list1.sort() # [1, 2, 3]
# 获取列表的长度(元素个数)
len([1,2,3]) # 3
列表推导式
Python 提供列表+for-in
的方式可以方便地从一个列表创建另一个列表。格式为:[表达式 for 变脸 in 列表 if 条件],其中,if 条件
可省略
list1 = [1, 2, 3]
[x+2 for x in list1] # [3, 4, 5]
[x+2 for x in list1 if x > 2] # [5]
嵌套列表
列表可以嵌套,即:列表里的元素仍然是个列表。
用法跟普通元素列表一样。
list1 = [[1,2,3], 4, 5]
list1[0][1] #2
6. 数据结构之元组
元组
也是一些元素的集合(元素可重复),Python中通过小括号 ()
来定义一个元组
。
# 定义组
tuple1 = (1, 2, 3)
# 查看变量的类型
print(type(tuple1)) # <class 'tuple'>
# 下标获取元素
print(tuple1[0]) # 1
# 切片
print(tuple1[:2]) # (1, 2)
# 遍历元组
for t in tuple1:
print(t)
# 元素是否在元组内
print(1 in tuple1) # True
print(4 in tuple1) # False
元组又被成为n元组
,n
是元组中元素的数量。3个元素的元组就叫三元组,4个元素的元组就叫四元组。
虽然元组
的用法跟列表
差不多,但还是有区别的,元组中的元素不能改变,元组定义好了之后不能再添加、删除元素。
使用元组
的一个方便之处在于打包和拆包。
# 自动打包成元组
t = 1, 2, 3 #(1, 2, 3)
print(type(t)) # <class 'tuple'>
# 从元组拆包成变量
a, b, c = t
print(a) # 1
print(b) # 2
print(c) # 3
这个特性经常用在函数的返回值中。
6. 数据结构之字符串
在前面的代码中,我们已经使用过字符串了,Python中,通过''
或""
来定义字符串。
s = 'hello, world!'
如果把字符串中的每个字符看成列表中的每个元素。那么,列表中的很多操作都可以用在字符串中。
如:字符串拼接、根据下标查找字符、字符串切片、某字符(串)是否在当前字符串中等等。
字符串还定义了一些不同于列表的操作,如:判读字符串是否以某子串开头,字符串的分割等,大家可以自行探索。
字符串的格式化
我们之前用过下面这种方式格式化字符串
print('周长: %.2f' % perimeter)
%.2f
中的 f
代表输出浮点数,2
代表保留2位小数。还有%d
、%s
用来输出整数和字符串。
Python3 还提供下面这种更简便写法
a = 10
b = 2.3
print(f'a = {a}, b={b}')
这种方式适合变量多的情况,可读性很好。
6. 数据结构之集合和字典
集合
存储不可重复的元素,Python中用{}
来定义集合
。
s = {1, 2, 2, 3}
print(s) # {1, 2, 3}
当需要对元素去重的时,列表就不好使了,但使用集合
可以保证元素不重复。
字典
存储的是键值对
集合,Python中用{键:值}
来定义字典
。
d = {'name': '老渡', gender: '男'}
print(d)
print(d['name']) #老渡
字典
可以比列表
的优势在于,字典
的下标可以是任意数据类型,而列表
的下标只能是数字。
另外,字典
的键
是不能重复的。
集合
和字典
我们只说了它们存储的数据,但没讲它们的操作,大家可以按照列表
那节的思路自行查阅。
Python 中除了上面定义的内部类,还会用到各种各样的第三方类、模块。
Python 之所以强大正是因为它的第三方模块很强大,可以帮我们轻松完成需求。
以上就是本次分享的所有内容,如果你觉得文章还不错,欢迎关注公众号:Python编程学习圈,每日干货分享,发送“J”还可领取大量学习资料。或是前往编程学习网,了解更多编程技术知识。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。