Python学习笔记 - Python语法基础

前言

本篇博文主要介绍Python中的一些最基础的语法,其中包括标识符、关键字、内置函数、变量、常量、表达式、语句、注释、模块和包等内容。

一、标识符、关键字和内置函数

任何一种语言都离不开标识符和关键字,下面将介绍Python的标识符和关键字。

1.1 标识符

标识符就是变量、常量、函数、属性、类、模块和包等由程序员指定的名字。构成标识符的字符均有一定的命名规范,Python语言中标识符的命名规则如下:

  • 标识符由字母、数字、下划线('_') 组成,首字符可以是下划线('_') 或字母,但不能是数字字符。
  • 区分大小写,Myname 和 myname 是两个不同的标识符。
  • 标识符不能包含空格,但可以使用下划线来分隔其中的单词。例如,变量名greeting_message可行,但变量名 greeting message会引发错误。
  • 标识符不能是Python关键字,但可以包含关键字。例如,变量名class错误,但是变量名stud_class可以。
  • 不能使用Python内置的函数名作为自己的标识符。例如,print是内置函数名,不能用作标识符。

标识符命名建议

(1)变量名应既简短又具有描述性。例如, name比n好, student_name比s_n好, name_length比length_of_persons_name好
(2)慎用小写字母 l 和大写字母O,因为它们可能被人错看成数字1和0。

(3)变量名建议使用小驼峰命名法,函数名、类名建议使用大驼峰命名法。例如,studNo;StudInfo。

  • 合法的标识符示例:
身高         # 没错,中文也可以作为标识符,但十分不建议使用,这不是好的编程习惯
identifier   # 英文单词作为标识符
userName     # 小驼峰命名法
UserName     # 大驼峰命名法
user_name    # Linux内核命名法
_sys_val     # 以下划线开头的标识符
  • 非法的标识符示例:
2mail     # 数字开头,标识符非法
room#     # 包含非法字符#,标识符非法
$name     # 包含非法字符$,标识符非法
class     # 使用Python关键字作为标识符,非法

注意》# 和 $ 不能构成标识符。C/C++语言是可以使用美元符号($) 作为标识符的,这一点跟Python语言是有区别的。需要注意一下。

1.2  Python的关键字

关键字是类似于标识符的字符序列,由语言本身定义好。Python语言中有 35 个关键字,只有三个,即 False、None 和 True 是首字母大写。

具体内容见下表1-1所示:

表1-1 Python关键字
FalseNoneTrueandas
assertasyncawaitbreakclass
defdefdelelifelse
exceptfinallyforfromglobal
ifimportinislambda
nonlocalnotorpassraise
returntrywhilewithyield

我们可以在Python Shell交互式命令行中查看Python所包含的所有关键字信息:

# 首先,查看当前已安装版本的Python版本号
>>> import sys
>>> print(sys.version)
3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)]
>>> sys.version
'3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)]'
# 然后,查看当前Python版本包含的所有关键字信息
>>> import keyword
>>> keyword.kwlist
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 
'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 
'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 
'try', 'while', 'with', 'yield']
# 打印Python关键字的个数
>>> len(keyword.kwlist)
35
>>>

说明》可以看到,Python-3.10.4 版本的所有关键字一共有35个,而之前的 Python 3 版本的关键字只有33个,其中,'async', 'await' 这两个关键字是在 Python-3.5 版本中新添加的,用于异步编程。

1.3  Python内置函数

上面这些内置函数的名字也不应该作为标识符,否则 Python 的内置函数会被覆盖。

示例:内置函数使用实例。

>>> abs(-1024)    # 求绝对值函数
1024
>>> bin(255)      # 求255的二进制表示
'0b11111111'
>>> round(3.1415726, 3)  # 四舍五入,保留小数点后3位有效数字
3.142

注意》在Python 2.x 中,print 是关键字而不是函数。上面这些内置函数(如 unicode())只是 Python 2.x 的内置函数,为了保证 Python程序具有更好的兼容性,程序也不应该使用这些内置函数的名字作为标识符。

二、变量和常量

2.1  变量

  • Python是弱类型语言

Python是弱类型语言,弱类型包含两方面的含义:

(1)所有的变量无须事先声明即可使用,或者说对从未用过的变量赋值就是声明了该变量,并且不需要指定数据类型。

(2)变量的数据类型可以动态改变,同一个变量可以一会儿是数值类型,一会儿是字符串类型。

因此,Python语言也可以看做是一种动态类型语言

动态类型语言会在运行期间检查变量或表达式的数据类型,主要有 Python、PHP 和 Object-C 等语言。与动态类型语言相对应的是静态类型语言,静态类型语言会在编译期间检查变量或表达式的数据类型,如 Java 和 C/C++ 语言等。

在 Python 中声明变量时不需要指定它的数据类型,只要是给一个标识符赋值就声明了一个变量,示例代码如下:

hello = "HelloWorld"       # 第1行
score_for_student = 0.0    # 第2行
y = 20                     # 第3行
y = True                   # 第4行

代码第1行、第2行和第3行分别声明了三个变量,这些变量声明时不需要指定数据类型,你赋给它什么数值,它就是该类型变量了。注意代码第4行是给变量 y 赋一个布尔值 True,虽然 y 已经保存了整数类型值 20,但它也可以接收其他数据类型的值。

提示》Python是动态类型语言,它不会检查数据类型,在变量声明时不需要指定数据类型。这一点与 Swift 和 Kotlin 语言不同,Swift 和 Kotlin 虽然在声明变量时也可以不指定数据类型,但是它们的编译器会自动推导出该变量的数据类型,一旦该变量确定了数据类型,就不能再接收其他类型数据了。而Python的变量可以继续接收其他类型数据。

2.2  常量

在很多编程语言中常量的定义是一旦初始化后就不能再被修改的。而Python不能从语法层面上定义常量,Python没有提供一个关键字(const)使得变量不能被修改。所以在Python中只能将变量当成常量使用,只是不要修改它。那么这就带来了一个问题,变量可能会在无意中被修改,从而引发程序错误。解决此问题要么靠程序员自律和自查,要么通过一些技术手段使变量不能修改。

提示》Python作为解释性动态语言,很多情况下代码安全需要靠程序员自查。而Java和C/C++等静态类型语言的这些问题会在编译期被检查出来。

三、Python的注释

Python源代码的注释有两种形式:

  • 单行注释
  • 多行注释(又称为文档注释)

        编写注释的目的是阐述代码要做什么,以及如何做的。要成为一名专业以及出色的程序员,最值得养成的习惯之一是,在代码中编写清晰、简洁的注释

3.1  单行注释

        Python程序单行注释使用井号 “#”,使用时 # 位于注释行的开头,# 后面有一个空格,接着就是注释内容。跟在 # 号后面直到这行结束为止的内容都将被解释器忽略掉。

使用单行注释示例代码如下:

# coding=utf-8                # 1
# 代码文件: hello.py           # 2

# _hello = "HelloWorld"       # 3
# score_for_student = 100     # 4
y = 20
y = "大家好"
print(y)      # 打印变量y      # 5

代码第1处和第2处中的 # 号是进行单行注释,# 号也可以连续注释多行,见代码第3处和第4处,还可以在一条语句的尾端进行注释,见代码第5处。

注意代码第1处的 # coding=utf-8 的注释作用特殊,是设置Python代码源文件的编码集,该注释语句必须放在源文件的第一行或第二行才能有效,它还有替代写法:

#!/usr/bin/python
# -*- coding: utf-8 -*-

其中 #!/usr/bin/python 注释是在 Unix、Linux 和 macOS 等系统平台上安装多个Python版本时,具体指定哪个版本的Python解释器。一般而言,在Linux操作系统上的Python解释器默认是Python 2.7.5版本的,如果要使用Python 3.x 版本的解释器,应该写成:#!/usr/bin/python3

提示》在PyCharm 和 Sublime Text 开发工具中单行注释可以使用快捷键,在Windows系统下的具体步骤是:选中一行或多行代码然后按住 “Ctrl + /” 组合键进行注释。去掉注释也是选中代码后按住 “Ctrl + /” 组合键。

注意》在程序代码中,对容易引起误解的代码进行注释是很有必要的,但应避免对已清楚表达信息的代码进行注释。需要注意的是,频繁地注释有时反映了代码的低质量。当觉得被迫要加注释时,不妨考虑一下重写代码使其更清晰。

3.2  多行注释

多行注释是指一次性将程序中的多行代码注释掉,在Python程序中使用三个单引号或三个双引号将注释的内容括起来。

示例程序如下:

# 这是一行简单的注释
print("Hello World.")

'''
这里面的内容全部是多行注释
Python语言真的很简单
'''

# print("这行代码被注释掉了,将不会被编译、执行")

"""
这是用三个双引号括起来的多行注释
Python同样是允许的
"""

        此外,添加注释也是调试程序的一个重要方法。如果觉得某段代码可能有问题,可以先把这段代码注释掉,让Python解释器忽略这段代码,再次编译、运行,如果程序可以正常执行,则可以说明错误就是由这段被注释代码引起的,这样就缩小了错误所在的范围,有利于定位问题和排错;如果依然出现相同的错误,则可以说明错误不是由这段被注释代码引起的,同样也缩小了错误所在的范围。

四、Python语句

Python程序代码是由关键字、标识符、表达式和语句等内容构成的,语句是代码的重要组成部分。

语句关注代码的执行过程,如 if、for 和 while 等。在Python语言中,一行代码表示一条语句,语句结束可以加分号,也可以省略分号。

示例代码如下:

# coding=utf-8
# 代码文件:chapter4/4.4/hello.py

_hello = "HelloWorld"
score_for_student = 10.0;  # 没有错误发生
y = 20

name1 = "Tom"; name2 = "Tony"  # 1

提示从编程规范的角度讲,语句结束时不需要加分号,而且每行至多包含一条语句。代码第1处的写法是不规范的,推荐使用:

name1 = "Tom"
name2 = "Tony"

Python 还支持链式赋值语句,如果需要给多个变量赋相同的值,可以表示为:

a = b = c = 10

上面这条语句是把整数10赋值给 a、b、c 三个变量。

另外,在 if、for 和 while 代码块的语句中,代码块不是通过大括号("{ }")来界定的,而是通过缩进,缩进在一个级别的代码在相同的代码块中。

# coding=utf-8
# 代码文件:chapter4/4.4/hello.py

_hello = "HelloWorld"
score_for_student = 10.0;  # 没有错误发生
y = 20

name1 = "Tom"; name2 = "Tony"

# 链式赋值语句
a = b = c = 10

if y > 10:
    print(y)                    # 1
    print(score_for_student)    # 2
else:
    print(y * 10)               # 3
print(_hello)                   # 4

代码第1处和第2处是同一个缩进级别,它们在相同的代码块中。而代码第3处和第4处不在同一个缩进级别中,它们在不同的代码块中。

提示》一个缩进级别一般是一个制表符(Tab)或4个空格,考虑到不同的编辑器制表符显示的宽度不同,大部分编程语言规范推荐使用4个空格作为一个缩进级别。

五、模块

        Python中一个模块就是一个源文件,模块是保存代码的最小单位,模块中可以声明变量、常量、函数、属性和类等Python程序元素。一个模块提供可以访问另一个模块中的程序元素。

下面通过示例介绍模块的作用。现有两个模块module1 和 hello 。module1 模块代码如下:

# coding=utf-8
# 代码文件: HelloProj/module1.py

y = True
z = 10.10

print("进入module1模块")

hello 模块会访问 module1 模块的变量,hello 模块的代码如下:

# coding-=utf-8
# 代码文件: HelloProj/hello.py

import module1         # 导入module1模块       ---1
from module1 import z  # 导入module1模块的变量z ---2

y = 20
# z = 20.20

print(y)	       # 访问当前模块变量y    ---3
print(module1.y)   # 访问module1模块变量y ---4
print(z)           # 访问module1模块变量z ---5

上述代码中hello模块要访问module1模块的变量 y 和 z。为了实现这个目的,可以通过两种 import 语句导入模块module1中的代码元素。

  • import  <模块名>,见第1处代码。这种方式会导入模块所有代码元素,访问时需要加“模块名”,见代码第4处:module1.y,module1是模块名,y 是模块module1中的变量。
  • from <模块名> import <代码元素>,见第2处代码。这种方式只是导入特定的代码元素,访问时不需要加“模块名”,见第5处代码的变量 z。但是需要注意的是,当变量 z 在当前模块中也有时,module1中的变量 z 会被屏蔽掉,即只有当前模块的变量 z 会生效。

运行 hello.py 代码输出结果如下:

F:\python_work\Python基础\HelloProj>python hello.py
进入module1模块
20
True
10.1

# 如果把hello.py模块中的 "# z = 20.20" 注释去掉,则运行结果如下:
F:\python_work\Python基础\HelloProj>python hello.py
进入module1模块
20
True
20.2

从运行结果可见,import 语句会运行导入的模块,注意示例中使用了两次 import 语句,但只执行了一次module1模块的内容。

模块事实上提供了一种命名空间(namespace)。同一个模块内部不能有相同名字的代码元素,但是不同模块之间可以,上述示例中的变量 y 就在两个模块中都有。

  • 命名空间:也称为名字空间、名称空间等,它表示者一个标识符(identifier)的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处在其他命名空间中。

六、Python中的包(package)

        如果有两个相同名字的模块,应如何防止命名冲突呢?答案就是使用包(package),很多编程语言都提供了包,例如 Java、Kotlin 等,它们的作用都是一样的,即提供一种命名空间。

6.1  创建包

        现在我们重构一下第5节中的示例,现有每个hello模块,它们放在不同的包 com.pkg1 和 com.pkg2 中,如下图1所示,从图中可见包是按照文件夹的层次结构管理的,而且每个包下面都会有一个 __init__.py 文件,它告诉Python解释器这是一个包,这个文件内容一般情况下是空的,但可以编写代码。

        既然包是一个文件夹 + 一个空的 __init__.py 文件,那么开发人员就可以自己创建包了。笔者推荐使用 PyCharm 软件工具创建,它在创建文件夹的同时还会创建一个空的 __init__.py 文件,十分方便。

        具体步骤:使用 PyCharm 打开创建的项目,右击项目选择 “New —> Python Package”菜单,如下图2所示,在弹出的对话框中输入包名:com.pkg,其中 com 是一个包,pkg 是它的下一层级的包,中间用点号(.)分隔。

图1  包层次
图2  PyCharm项目中创建包

6.2  导入包

        包创建好后,将两个 hello 模块放到不同的包 com.pkg1com.pkg2 中。由于 com.pkg1 的hello模块需要访问 com.pkg2 的 hello 模块中的代码元素,那么如何导入呢?事实上还是通过 import 语句,需要在模块前面加上包名。

重构第5节中的示例,com.pkg2 的 hello 模块的代码内容如下:

# coding=utf-8
# 代码文件: HelloProj2/com/pkg1/hello.py

y = True
z = 10.10

print("进入com.pkg2.hello模块")

com.pkg1 的 hello 模块的代码内容如下:

# coding=utf-8
# 代码文件: HelloProj2/com/pkg1/hello.py

import com.pkg2.hello as module1       # ---1
from com.pkg2.hello import z           # ---2

y = 20

print(y)          # 访问当前模块变量y
print(module1.y)  # 访问com.pkg2.hello模块的变量y ---3
print(z)          # 访问com.pkg2.hello模块的变量z

        代码第1处使用 import 语句导入 com.pkg2.hello 模块所有代码元素,由于 com.pkg2.hello 模块名 hello 与当前模块名冲突,因此需要使用 as module1 语句为 com.pkg2.hello 模块提供一个别名 module1,访问时需要加上 module1. 前缀。

        代码第2处是导入 com.pkg2.hello 模块中的变量 z。from com.pkg2.hello import z 语句也可以带有别名,该语句可以修改为如下代码:

from com.pkg2.hello import z as x  # 为变量z起一个别名x
print(x)  # 访问 com.pkg2.hello 模块中的变量z

使用别名的目的是防止发生命名冲突,也就是说要导入的变量 z 的名字在当前模块中已经存在了,为了以示区分,所以给 z 起了一个别名 x。

在PyCharm中选中 com.pkg1.hello 模块文件,鼠标右击,在弹出的菜单栏中,鼠标左击运行按钮,运行结果如下:

"D:\Program Files\Python\python.exe" F:/python_work/Python基础/HelloProj2/com/pkg1/hello.py
进入com.pkg2.hello模块
20
True
10.1

进程已结束,退出代码0

遇到的问题:在Dos终端中使用 python 命令运行 com\pkg1\hello.py 文件,发现会报错,报错信息如下:

F:\python_work\Python基础\HelloProj2>python .\com\pkg1\hello.py
Traceback (most recent call last):
  File "F:\python_work\Python基础\HelloProj2\com\pkg1\hello.py", line 4, in <module>
    import com.pkg2.hello as module1       # ---1
ModuleNotFoundError: No module named 'com'

解决办法:在执行报错的模块 com\pkg1\hello.py 文件中添加如下内容:

import sys
import os
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(os.path.split(rootPath)[0])

保存成功后,然后在Dos命令行中就可以成功执行了,运行结果如下:

F:\python_work\Python基础\HelloProj2>python .\com\pkg1\hello.py
进入com.pkg2.hello模块
20
True
10.1

参考链接

ModuleNotFoundError: No module named ‘XXX‘ 解决方法

参考

《Python从小白到大牛(第1版-2018)》

《疯狂Python讲义(2018.12)》

《Python编程:从入门到实践(2016.7)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值