Python标识符

想象一下,你要在代码世界里“开公司”做项目,那每个变量、函数、类都得有个独一无二的“代号”,这“代号”就是「标识符」~ 所以接下来要说的就是,把 Python 标识符的规矩讲明白,保证有趣又好懂👇

一、基础规则:能叫什么?不能叫什么?

Python 里的标识符,就像给代码里的组件取名字,得守点小规矩:

1. 允许的字符:字母、数字、下划线

比如想给变量取个名字,可以用 my_name(即字母+下划线)、age18(字母+数字)、_secret(下划线开头)……但注意不能有空格、标点符号(除了下划线)
举个🌰:

1
2
3
my_name = "小明"   # 合法:字母+下划线
age18 = 18 # 合法:字母+数字
_secret = "藏起来" # 合法:下划线开头

2. 不能以数字开头

如果一上来就用数字,Python 看不懂你写的什么,懵圈了,这给我干哪来了!
反面教材🌰:

1
18age = 18  # 报错!不能以数字开头,Python看不懂“18age”是什么!

3. 区分大小写

Python里,Namename 完全是两个不同的标识符!就像“张三”和“张叁”是两个人
举个🌰:

1
2
3
4
Name = "大写的名字"
name = "小写的名字"
print(Name) # 输出:大写的名字
print(name) # 输出:小写的名字

二、特殊下划线

在Python里,下划线开头的标识符,往往有特殊身份,就像电影里带暗号的接头人~

1. 单下划线开头:_foo(我称之为低调的类属性)

当你在类里看到 _foo 这样的变量或者方法名的时候,它相当于在说:“我是内部用的,外面最好别直接访问我”
就好比公司里的内部文档,外人想调阅得走流,即通过类提供的接口来访问,不能随随便便 from xxx import * 直接把它暴露出去

举个类的例子🌰(这里你即使暂时看不懂类也没关系,先感受下划线意思):

1
2
3
4
5
6
7
8
9
10
11
12
class Person:
def __init__(self):
self.name = "公开姓名"
self._age = 18 # 单下划线开头,暗示内部属性

def get_age(self): # 提供接口,让外部可以间接拿到_age
return self._age

p = Person()
print(p.name) # 直接访问公开属性,输出:公开姓名
print(p.get_age())# 通过接口访问_age,输出:18
# print(p._age) # 虽然能硬访问,但不推荐,相当于没走流程偷看内部文档

2. 双下划线开头:__foo(私有成员,自我保护)

双下划线 __foo 开头的标识符,Python会自动做一层名字混淆,相当于给它加了个保险箱,外部想直接碰它,难度直线上升!
这就像公司里的高层机密文档,不是随便谁都能看的

举个🌰(还是类的例子,感受意思即可):

1
2
3
4
5
6
7
8
9
10
class Cat:
def __init__(self):
self.__nickname = "喵小秘" # 双下划线开头,变成私有属性

def show_nickname(self): # 提供专门的方法,才能让外部看到
print(self.__nickname)

c = Cat()
# print(c.__nickname) # 直接访问?报错!Python:“年轻人,这是私有滴,不能碰!”
c.show_nickname() # 通过方法访问,输出:喵小秘

3. 双下划线开头+结尾:__foo__(Python的官方暗号)

这种格式是Python给自己留的特殊通道,比如最常见的 __init__()(即类的构造函数,创建对象时自动触发)、__str__()(控制对象打印成什么样)……
你可以理解成:“这是Python内置功能的专属标识,别瞎用!”

举个🌰(经典的__init__和__str__):

1
2
3
4
5
6
7
8
9
class Dog:
def __init__(self, name): # __init__是构造函数,创建对象时自动调用
self.name = name

def __str__(self): # __str__控制print(dog)时输出啥
return f"一只叫{self.name}的狗"

d = Dog("旺财")
print(d) # 输出:一只叫旺财的狗,因为__str__定义了打印格式

三、小彩蛋:一行写多条语句(分号 ; 助攻)

Python里,你还可以用分号 ; 把多条语句塞到同一行,就像买奶茶时,同时备注要三分糖、去冰、加珍珠

举个🌰:

1
2
3
4
5
print("hello"); print("Python"); print("你好")
# 执行后会依次输出:
# hello
# Python
# 你好

不过要注意:这种写法适合简短代码,太长的话可读性就崩了,所以别贪多,适度用用就行

来简简单单总结一下标识符的“取名守则”

  • 能由字母、数字、下划线组成,但数字不能开头~
  • 大小写敏感(Aa不是同一个东西)~
  • 下划线开头的有特殊含义:_foo(低调内部货)、__foo(私有藏起来)、__foo__(Python官方通道)
  • 想一行写多条语句?分号 ; 帮你忙

Python保留字,代码里的禁区警示牌

打个比方,假如Python世界里有一批专属贵宾席位,这些位置被Python官方霸占了,我们写代码时绝对不能抢。而这些席位就是保留字(关键字)。

一、什么是保留字?

保留字是Python语言预先定义好的特殊单词,每个都有特定语法功能,就像交通规则里的“红灯停、绿灯行”。你不能把这些规则牌拆了自己用,不然整个语言逻辑就会乱套

二、Python保留字全名单

先把所有保留字列出来,为了方便理解,每个关键字贴个功能标签:

保留字 功能类比 保留字 功能类比 保留字 功能类比
and 逻辑“与”(和) exec 执行外部代码(进阶) not 逻辑“非”(取反)
assert 断言(调试时检查条件) finally 异常处理的最终保障区 or 逻辑“或”(或者)
break 打断循环(跳出循环) for 循环遍历(比如遍历列表) pass 占位符(代码还没想好,先占坑)
class 定义类(面向对象核心) from 模块导入专用(从哪导入) print 打印输出(新手最爱🤣)
continue 跳过当前循环,继续下一轮 global 声明全局变量 raise 主动抛异常(告诉程序出错了)
def 定义函数 if 条件判断(如果…那么…) return 函数返回结果
del 删除对象引用(回收变量) import 导入模块(把工具包拿进来) try 异常捕获(试试这段代码,出错了处理)
elif 条件判断的否则如果” in 判断成员关系(在…里面吗?) while 循环(满足条件就一直做)
else 条件或循环的否则分支 is 判断对象身份(是不是同一个?) with 上下文管理(比如自动关文件)
except 异常处理的except捕获区 lambda 定义匿名函数(超简短函数) yield 生成器专用(逐步产出数据)

看完上面的表,是不是感觉每个保留字都有自己的岗位职责?就像公司里的每个岗位都有专属工作,不能乱串

三、误用保留字会怎样?

如果你偏要把保留字当变量名或者函数名,Python会直接给你丢个语法错误,相当于你抢了交警的指挥岗,交通直接瘫痪

举个🌰(错误示范):

1
2
if = 18  # 错误!if是保留字,不能当变量名
print(if)

运行后会报错:

1
SyntaxError: invalid syntax

人话:语法错误!你用了不能用的词!

四、如何快速判断是不是保留字?

有个简单的方法:在Python交互环境,或PyCharm里写代码时,试着把单词当变量名用,看会不会爆红或者报错
或者更主动点,记住,保留字都是Python语法的“脊梁骨”,用来控制流程、定义结构,像 if(判断)、for(循环)、def(函数)这些高频词,肯定是保留字!

五、趣味记忆口诀(可选)

把保留字串成顺口溜,没事念一念,印象更深
(押韵不重要,顺嘴就行🤣)

循环断跳有for、while,break、continue不能瞎;
条件分支if、elif、else,断言assert调试要检查;
定义函数def、类class,全局变量global得声明;
异常处理try、except、finally,主动抛错raise别犯傻;
导入模块import、from,逻辑运算and、or、not;
成员判断in、is,上下文管理with;
匿名函数lambda,生成器yield,占位符pass先占下;
del删引用,print输呱呱

现在你已经摸清Python保留字的脾气,写代码时,一定要绕开这些禁区,给变量、函数取名字前,先想想:这词是不是保留字?会不会抢了Python的饭碗?😎 要是拿不准,就打开Python交互模式,输入 import keyword; print(keyword.kwlist) ,能直接看到所有保留字列表,随时查岗

行和缩进

如果把 Python 代码比作一支舞蹈队,缩进就是队形规则——每个动作(即代码块)都得对齐,否则整个舞蹈(也就是程序逻辑)都得乱套

一、为什么是缩进?其他语言用大括号,Python为什么特立独行?

其他语言(比如 Java、C++)用 {} 划分代码块,像这样:

1
2
3
4
5
if (true) {
System.out.println("True");
} else {
System.out.println("False");
}

而 Python 偏不!它选择用缩进代替大括号,理由很简单:让代码更简洁、更readable(读得懂)

你可以这么想,如果所有代码都挤在一起,没有缩进,你得在大括号里找半天逻辑;但有了统一缩进,一眼就能看出哪些代码属于 if 分支,哪些属于 else 分支

二、缩进规则

Python 里,同一逻辑块的代码必须有相同的缩进量,好比舞蹈队里同一排的演员得站对齐

1. 示例:if-else 的缩进

看这段代码(4个空格缩进,最常见的选择):

1
2
3
4
5
6
if True:
print("进了if分支~") # 属于if的代码块,缩进4空格
print("还在if里~") # 同样缩进4空格,和上面是一伙的
else:
print("进了else分支~")# 属于else的代码块,缩进4空格
print("还在else里~") # 同样缩进4空格

执行后,因为 True 成立,会输出:

1
2
进了if分支~
还在if里~

2. 错误示范:缩进不一致,程序直接崩

如果缩进乱了,比如下面这样(else 分支里某行缩进少了):

1
2
3
4
5
6
if True:
print("进了if分支~")
print("还在if里~")
else:
print("进了else分支~")
print("这里缩进乱了!") # 错误:和上面else的缩进不一样

Python 会直接报错:

1
IndentationError: unindent does not match any outer indentation level

人话:缩进不正确!你这行和外面的缩进层次对不上!

三、常见缩进错误 & 排雷技巧

Python 对缩进格式一致性要求到苛刻,新手很容易踩坑,常见错误有两种:

1. 错误1:Tab 和 空格混用

有的编辑器按 Tab1个制表符,有的用 空格(比如4个空格代表一级缩进)。如果代码里既有 Tab 又有空格,Python 会懵圈:到底谁和谁是一伙的?

举个🌰(混合用了Tab和空格):

1
2
3
if True:
print("用了4个空格缩进") # 空格
print("这里用了Tab") # Tab → 错误!和上面格式不一致

运行后报错:

1
IndentationError: inconsistent use of tabs and spaces in indentation

2. 错误2:意外缩进(即unexpected indent)

有时候不小心多按了空格/Tab,某行代码莫名缩进了,Python 也会报错:

1
2
3
if True:
print("正常缩进")
print("这里多按了个空格→意外缩进!") # 错误

报错:

1
IndentationError: unexpected indent

排雷技巧:

  • 选一种缩进风格贯穿始终(推荐 4个空格,PyCharm 等编辑器也默认用4空格)。
  • 用编辑器/IDE 的“显示空白符”功能(比如 PyCharm 里打开 查看 → 活动编辑器 → 显示空白),能直观看到 Tab 和 空格,避免混用。

四、缩进层次:嵌套代码的“队形纵深”

当代码有多层嵌套(比如 if 里套 if,循环里套函数),每一层嵌套都要多一级缩进,就像舞蹈队里的方阵纵深,第一层站第一排,第二层站第二排,以此类推

举个多层嵌套的🌰:

1
2
3
4
5
6
7
8
if 成绩 > 90:
print("优秀")
if 单科 > 95:
print("单科接近满分") # 比外层if多一级缩进(比如4→8空格)
else:
print("单科还能冲一冲")# 同样和内层if的else对齐
else:
print("继续努力")

五、类比

可以把理解成舞蹈动作,缩进是动作的归属,即,哪个动作属于哪个分支/循环,全看缩进对齐

  • 同一分支的代码 → 同一排演员,同一缩进
  • 嵌套分支的代码 → 后排演员,多一级缩进
  • 混用 Tab/空格 → 队伍里混进了穿不同鞋子的人,队形大乱
  • 意外缩进 → 某演员站错排,整个方阵崩坏

多行语句、引号与注释

如果把 Python 代码比作一篇文章,多行语句是分段换行的技巧,引号是给文字加引号的花样,注释则是写给自己悄悄话

一、多行语句

写文章时,长句子一口气写不下,得换行;Python 里长代码也一样,但得守点换行规矩

1. 用反斜杠“ \ ”手动换行

如果一行代码太长,比如多个变量相加,可以用 反斜杠 \ * 告诉 Python:这行没结束,下一行接着来

举个🌰:

1
2
3
4
total = item_one + \
item_two + \
item_three
# 反斜杠后要紧跟换行,不能有空格!否则会报错~

就像写文章时,在换行处加个续行符,告诉读者这句话还没说完,下一行继续

2. 括号里自动换行([], {}, ())

如果代码里有 列表[]、字典{}、元组() 这些带括号的结构,Python 会自动识别括号里的换行,不用手动加 \

举个🌰(列表里换行):

1
2
days = ['Monday', 'Tuesday', 'Wednesday',
'Thursday', 'Friday'] # 括号内换行,Python自动认

再比如函数调用传参(括号里换行):

1
2
3
4
5
result = calculate(
num1,
num2,
num3
)

这种括号内自由换行,就像文章里括号内的解释可以分多行写,Python 能智能识别

二、Python 引号

写文章时,引语可以用单引号、双引号;Python 里“字符串”也有三种引号选择,各有特色~

1. 单引号 ‘’ 和 双引号 “”

单引号和双引号功能几乎一样,选哪个看个人习惯。主要用来包短字符串,比如单词、句子

举个🌰:

1
2
word = 'Python'  # 单引号包单词
sentence = "人生苦短,我用Python" # 双引号包句子

如果字符串里包含单引号,就用双引号包;包含双引号,就用单引号包,避免引号打架

比如:

1
2
text = "He said, 'Python is easy!'"  # 字符串里有单引号,外层用双引号
text2 = 'She said, "Python is fun!"' # 字符串里有双引号,外层用单引号

2. 三引号 ‘’’ ‘’’ 或 “”” “””:多行字符串+注释

三引号就像大括号,能包跨越多行的字符串,还能当多行注释使

(1)包多行字符串

比如写一段散文式的字符串:

1
2
3
4
5
6
7
paragraph = """
从前有座山,
山里有座庙,
庙里有个老和尚讲故事~
"""
print(paragraph)
# 输出会保留换行和缩进,原封不动打印~

(2)当多行注释用

因为三引号包起来的内容如果没被赋值给变量,Python 会把它当空气忽略掉,所以可以用来写多行注释

比如:

1
2
3
4
5
6
7
8
9
'''
这是一段多行注释,
用来解释下面的代码逻辑:
1. 先获取用户输入
2. 再处理数据
3. 最后输出结果
'''
name = input("请输入名字:")
print(f"你好,{name}")

也可以用双引号的三引号 “”” “”””,效果一样

三、Python 注释

写文章时,会加批注、注释帮读者理解;代码里的注释,是帮自己快速看懂逻辑

1. 单行注释:# 开头

井号 # 后面的内容,Python 会直接忽略, commonly 用来写单行说明

举个🌰:

1
2
# 这是单行注释,解释下面代码的作用
print("Hello, Python!") # 也可以跟在代码后面,解释这行干啥

就像文章里的脚注,一行一个小说明

2. 多行注释:三引号包起来

前面提过,三引号如果没被赋值,就会被当注释, 所以可以用来写大段解释,比如函数用途、整个模块的说明

举个🌰(双引号三引号版):

1
2
3
4
5
6
7
8
9
"""
这个脚本用来实现用户登录功能:
步骤1:读取用户输入的账号密码
步骤2:和数据库存储的账号密码比对
步骤3:返回登录结果
"""
def login():
# 此处写登录逻辑...
pass

把代码当文章写

  • 多行语句 → 文章的换行规则:长句用 \ 续行,括号里自由换行
  • 引号 → 文章的号风格:短引语用单/双引号,大段文字用三引号
  • 注释 → 文章的批注/解说:单行用 # 当脚注,多行用三引号当大段说明

空行、输入输出与代码组织

如果把 Python 代码比作一座房子,空行是房间之间的走廊,输入输出是房子和外界的交互窗,代码组织是家具的摆放逻辑

一、空行

写代码和写文章一样,密密麻麻挤在一起,读起来累;适当加空行,逻辑更清晰

1. 空行的作用

  • 函数/类方法之间加空行:比如一个文件里有多个函数,用空行隔开,一眼能分清这是函数 A,那是函数 B
  • 类和函数之间加空行:类是大模块,函数是小工具,空行分隔让结构更明确~

举个🌰:

1
2
3
4
5
6
7
8
9
10
11
12
def func1():
print("函数1的功能")

def func2(): # 和上面func1之间空一行,区分不同函数
print("函数2的功能")

class MyClass:
def method1(self):
print("类里的方法1")

def method2(self): # 类内方法之间,也可以酌情空行
print("类里的方法2")

2. 空行不是语法要求,但灵魂需要

Python 解释器不管有没有空行,都能运行;但空行是写给人看的~ 就像房子里的走廊,没走廊也能走,但有了更舒服、好整理

二、等待用户输入

程序不是孤岛,得和用户互动。Python 里用 input()( Python3 )或 raw_input()( Python2 )让程序等用户输入

1. 基本用法:等用户输入,按回车继续

比如写个按回车退出,按其他键显示内容的小交互:

1
2
3
input("按下 enter 键退出,按其他键+回车显示...\n")
# 运行后,程序暂停,等你输入~
# 按回车 → 程序结束;按其他键+回车 → 程序也结束(但可以捕获输入内容)

2. 捕获用户输入内容

要用变量接住用户输入的内容,比如:

1
2
name = input("请输入你的名字:")
print(f"你好,{name}!")

运行后,你输入小明,程序会输出你好,小明!。就像房子装了语音对话装置,能回应用户

三、同一行写多条语句:紧凑但谨慎用

Python 允许一行写多个语句,用 分号 ; 隔开~ 但别滥用,否则代码像挤地铁,可读性差

1. 简单示例

1
2
import sys; x = 'Python'; sys.stdout.write(x + '\n')
# 一行里做了三件事:导入模块、定义变量、打印内容

2. 什么时候用?

适合写极简短、逻辑关联强的语句,比如测试代码、单行脚本。 但项目里尽量一行一条语句,方便调试和阅读

四、print 输出

print() 是 Python 最常用的输出窗口,默认输出后换行;但也能控制不换行

1. 默认换行输出

1
2
3
4
5
print("第一行")
print("第二行")
# 输出:
# 第一行
# 第二行

2. 不换行输出(Python2 风格,少用)

Python2 里可以用逗号 ,print 不换行,但 Python3 里更推荐用 end 参数~

Python2 示例(现在少用,了解即可):

1
2
3
print "第一部分",
print "第二部分"
# 输出:第一部分第二部分

Python3 更优雅的写法(用 end):

1
2
3
print("第一部分", end="")  # end="" 表示输出后不加换行符
print("第二部分")
# 输出:第一部分第二部分

五、多个语句构成代码组

ifwhiledefclass 这些关键字开头的语句,后面要跟冒号 :,再跟缩进的代码组

1. 示例:if 语句的代码组

1
2
3
4
5
6
7
score = 85
if score >= 90:
print("优秀")
elif score >= 80:
print("良好") # 属于elif的代码组,缩进一致
else:
print("继续努力") # 属于else的代码组,缩进一致

2. 代码组的本质

同一代码组的语句,必须有相同的缩进,比如都4个空格,就像同一队的队友站同一排

六、命令行参数

运行 Python 脚本时,可以通过命令行给程序传参数,像给房子外接拓展装备

1. 查看帮助:python -h

在终端输入 python -h(或 python --help),能看到 Python 命令行的帮助信息,比如:

1
2
3
4
5
6
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ... 
Options and arguments:
-c cmd : 执行字符串里的代码
-d : 开启调试模式
-h : 显示帮助信息
...

2. 脚本接收参数:sys.argv

如果写了个脚本 test.py,想让用户运行时传参数,可以用 sys.argv 读取~

示例 test.py

1
2
import sys
print("传入的参数是:", sys.argv)

终端运行 python test.py 张三 20,输出:

1
传入的参数是: ['test.py', '张三', '20']

sys.argv[0] 是脚本名,sys.argv[1] 是第一个参数,依此类推

以上内容,便是基础语法的全部内容,下一部分内容将开始讲解 Python 的变量类型。下面是一些问题,请动手做一做:

一、基础选择题

  1. 以下关于 Python 缩进的说法,错误的是?( )
    A) 同一代码块必须用相同数量的空格缩进
    B) 缩进可以用 Tab 或空格,但不能混用
    C) IndentationError: unexpected indent 通常是因为某行代码“意外多了缩进”
    D) Python 允许不同代码块用不同数量的缩进,只要各自内部统一

  2. 要让 Python 打印内容后不换行,以下 Python3 写法正确的是?( )
    A) print("Hello", end="")
    B) print("Hello", ",")
    C) print "Hello", (Python2 风格,Python3 不支持)
    D) print("Hello") 后手动加 \n

  3. 关于 Python 引号的使用,正确的是?( )
    A) 单引号和双引号完全等价,随便选
    B) 三引号 ''' 只能用来写多行字符串,不能当注释
    C) 如果字符串里包含单引号,外层必须用双引号包裹
    D) 三引号 """ 包裹的字符串,换行和缩进会被原封不动保留

  4. 以下关于空行的说法,正确的是?( )
    A) 空行是 Python 语法要求,必须严格按行数加
    B) 函数之间加空行是为了让代码运行更快
    C) 空行能分隔不同功能的代码,提升可读性
    D) 类内部的方法之间绝对不能加空行

  5. 运行 python test.py 小明 18 时,sys.argv 的结果是?( )
    A) ['test.py', '小明', '18']
    B) ['小明', '18']
    C) ['python', 'test.py', '小明', '18']
    D) 报错,因为不能传中文

  6. 以下代码运行后,输出结果是?

    1
    2
    print("Hello")
    print("Python")

    A) HelloPython
    B) Hello
    Python
    C) 报错
    D) 只打印 Hello

  7. 看代码,选出注释正确的选项(多选):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 这是单行注释
    print("第一行")

    '''
    这是
    多行
    注释
    '''
    print("第二行")

    A) # 这是单行注释 是单行注释,会被执行
    B) 三引号 ''' 包裹的内容是多行注释,不会被执行
    C) print("第一行") 会打印内容,print("第二行") 不会
    D) 注释的作用是给代码加说明,Python 会忽略注释内容

  8. 关于以下多行语句写法,正确的是?

    1
    2
    3
    total = item_one + \
    item_two + \
    item_three

    A) 反斜杠 \ 后必须紧跟换行,不能有空格
    B) 可以把反斜杠换成逗号 , 达到同样效果
    C) 这种写法是错误的,Python 不允许一行拆多行
    D) 反斜杠可以随便加在代码任何位置

  9. 下面代码中,字符串的引号使用正确的是?

    1
    2
    3
    4
    word = 'Python'
    sentence = "I's learn Python"
    paragraph = """这是一段
    多行文字"""

    A) word 用单引号,完全没问题
    B) sentence 里有单引号 ',外层用双引号正确
    C) paragraph 用三引号包多行字符串,正确
    D) 以上全对

二、改代码除 Bug(考验语法细节)

题1:引号不匹配导致报错

下面代码运行会报错(SyntaxError: EOL while scanning string literal),请修正引号,让代码正常打印诗句~

1
2
3
poem = '床前明月光,
疑是地上霜。'
print(poem)

题2:缩进错误导致报错

下面代码因缩进问题报错(IndentationError),请修正缩进,让代码能正常输出“Hello Python”~

1
2
print("Hello")
print("Python") # 注意这行开头

题3:多行语句的反斜杠错误

下面代码想把长运算拆成多行,但反斜杠用错了导致报错,请修正~

1
2
total = 10 + 20 + \ 30 + 40  # 注意反斜杠位置
print(total)

三、写代码实现需求(考验知识应用)

题1:用三引号写介绍并打印

需求:

  • 三引号写一段“我的爱好”(至少两行,比如爱好是读书、跑步等)。
  • print() 把这段爱好打印出来。
  • 给代码加单行注释,解释每一步做了什么。

题2:用 input 互动并输出

需求:

  • input() 提示用户“请输入你的名字:”,并把输入的内容存到变量 name 里。
  • print() 输出“你好,name 的值!”(比如用户输入“阿花”,输出“你好,阿花!”)。

题3:给代码加空行提升可读性

需求:
下面代码没有空行,显得很挤~ 请在函数之间、函数和打印逻辑之间加空行,让结构更清晰~

1
2
3
4
5
6
def say_hello():
print("Hello!")
def say_goodbye():
print("Goodbye!")
say_hello()
say_goodbye()