第2章 Python基础语法

前言

Python是一种简洁、优雅且功能强大的编程语言,其语法设计注重可读性和简洁性,使得编写和维护代码变得更加容易。本章将介绍Python的基础语法,包括变量、数据类型、运算符、输入输出函数以及代码规范等内容,为后续章节打下坚实的基础。

本系列文章所使用到的示例源码:Python从入门到精通示例代码

2.1 变量与标识符

2.1.1 变量的概念与作用

变量是计算机程序中用于存储数据的命名存储位置。在Python中,变量实际上是对内存中存储的数据的引用或指针。变量的主要作用包括:

  • 存储和管理数据
  • 提高代码的可读性和可维护性
  • 方便数据的重复使用和修改

在Python中创建变量非常简单,只需要为变量赋值即可:

# 创建变量并赋值
name = "Python"
age = 30
is_programming_language = True

# 使用变量
print(name)  # 输出: Python
print(age)   # 输出: 30

2.1.2 变量的命名规则

标识符的组成

标识符是用来命名变量、函数、类、模块或其他对象的名称。Python中的标识符需要遵循以下规则:

  • 由字母、数字和下划线组成
  • 不能以数字开头
  • 区分大小写
  • 不能使用Python的关键字
# 有效的标识符
name = "Alice"
age_1 = 25
_private = "私有变量"
UserName = "用户名"

# 无效的标识符
# 1name = "Bob"      # 不能以数字开头
# my-var = 10        # 不能包含连字符
# class = "Python"   # 不能使用关键字

命名约定(PEP 8规范)

PEP 8是Python官方的代码风格指南,它提供了一些命名约定:

  • 变量和函数名使用小写字母,单词之间用下划线连接(snake_case)
  • 类名使用驼峰命名法(CamelCase)
  • 常量使用全大写字母,单词之间用下划线连接
  • 模块名使用简短的全小写名称
# 变量和函数名
user_name = "Alice"
max_retry_count = 3

def calculate_average(numbers):
    return sum(numbers) / len(numbers)

# 类名
class UserProfile:
    pass

# 常量
MAX_CONNECTIONS = 100
PI = 3.14159

关键字与保留字

Python有一组保留的关键字,这些关键字不能用作变量名或其他标识符名称。可以使用以下代码查看所有关键字:

import keyword
print(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']

2.1.3 变量的赋值与引用

Python中的变量赋值非常直观:

# 基本赋值
x = 10

# 多重赋值
a, b, c = 1, 2, 3

# 交换变量值
x, y = 10, 20
x, y = y, x  # 交换后 x=20, y=10

# 增强赋值
counter = 0
counter += 1  # 等同于 counter = counter + 1

在Python中,变量实际上是对象的引用。当我们将一个变量赋值给另一个变量时,两个变量实际上引用同一个对象:

a = [1, 2, 3]  # 创建列表对象
b = a          # b引用同一个列表对象

b.append(4)    # 修改列表对象
print(a)       # 输出: [1, 2, 3, 4]

2.1.4 变量的作用域简介

Python中的变量有不同的作用域,决定了变量在哪些部分的代码中可见:

  • 局部作用域:在函数内部定义的变量
  • 全局作用域:在模块级别定义的变量
  • 嵌套作用域:在嵌套函数中定义的变量
  • 内置作用域:Python预定义的变量
# 全局变量
global_var = "我是全局变量"

def my_function():
    # 局部变量
    local_var = "我是局部变量"
    print(local_var)
    print(global_var)  # 可以访问全局变量

    def nested_function():
        # 嵌套作用域变量
        nested_var = "我是嵌套变量"
        print(nested_var)
        print(local_var)   # 可以访问外层函数的局部变量
        print(global_var)  # 可以访问全局变量

my_function()
# print(local_var)  # 错误:局部变量在函数外不可见

2.1.5 常量的概念

常量是指在程序执行过程中值不应该改变的变量。Python没有内置的常量类型,但按照惯例,使用全大写字母命名的变量被视为常量:

PI = 3.14159
MAX_USERS = 100
DATABASE_URL = "mongodb://localhost:27017"

# 虽然可以修改,但按照惯例不应该这样做
# PI = 3.14  # 不推荐

2.2 数据类型概述

2.2.1 Python数据类型分类

Python是一种动态类型语言,提供了多种内置数据类型。这些数据类型可以分为两大类:

基本数据类型

  • 数字类型:int(整数)、float(浮点数)、complex(复数)
  • 字符串(str):文本序列
  • 布尔类型(bool):True或False
  • None类型:表示空值或不存在
# 数字类型
int_num = 42
float_num = 3.14
complex_num = 1 + 2j

# 字符串
text = "Hello, Python!"

# 布尔类型
is_active = True
is_completed = False

# None类型
result = None

复合数据类型

  • 列表(list):有序可变序列
  • 元组(tuple):有序不可变序列
  • 字典(dict):键值对集合
  • 集合(set):无序不重复元素集合
  • 冻结集合(frozenset):不可变的集合
# 列表
fruits = ["apple", "banana", "cherry"]

# 元组
coordinates = (10, 20)

# 字典
person = {"name": "Alice", "age": 30, "city": "Beijing"}

# 集合
unique_numbers = {1, 2, 3, 4, 5}

# 冻结集合
immutable_set = frozenset([1, 2, 3])

2.2.2 动态类型系统

Python是一种动态类型语言,这意味着变量的类型是在运行时确定的,而不是在编译时。同一个变量可以在不同时刻引用不同类型的对象:

x = 10       # x引用整数对象
print(type(x))  # 输出: <class 'int'>

x = "hello"  # x现在引用字符串对象
print(type(x))  # 输出: <class 'str'>

x = [1, 2, 3]  # x现在引用列表对象
print(type(x))  # 输出: <class 'list'>

2.2.3 type()函数的使用

type()函数用于获取对象的类型:

print(type(42))        # 输出: <class 'int'>
print(type(3.14))      # 输出: <class 'float'>
print(type("hello"))   # 输出: <class 'str'>
print(type([1, 2, 3])) # 输出: <class 'list'>
print(type({"a": 1}))  # 输出: <class 'dict'>
print(type(True))      # 输出: <class 'bool'>

2.2.4 isinstance()函数的使用

isinstance()函数用于检查对象是否是指定类型的实例:

x = 42
print(isinstance(x, int))    # 输出: True
print(isinstance(x, float))  # 输出: False
print(isinstance(x, (int, float)))  # 输出: True,检查多种类型

y = "hello"
print(isinstance(y, str))    # 输出: True

2.2.5 类型转换(显式与隐式)

Python支持两种类型转换:

显式类型转换(类型转换函数)

# 整数转换
print(int(3.14))    # 输出: 3
print(int("42"))    # 输出: 42

# 浮点数转换
print(float(42))     # 输出: 42.0
print(float("3.14")) # 输出: 3.14

# 字符串转换
print(str(42))       # 输出: "42"
print(str(3.14))     # 输出: "3.14"

# 布尔值转换
print(bool(0))       # 输出: False
print(bool(42))      # 输出: True
print(bool(""))      # 输出: False
print(bool("hello")) # 输出: True

隐式类型转换

Python在某些情况下会自动进行类型转换:

x = 10 + 3.14  # 整数和浮点数相加,整数被转换为浮点数
print(x)        # 输出: 13.14
print(type(x))  # 输出: <class 'float'>

y = "Hello, " + "World!"  # 字符串连接
print(y)        # 输出: Hello, World!

2.3 数字类型(int、float、complex)

2.3.1 整数类型(int)

Python中的整数可以是任意大小,不受限制:

# 十进制表示
decimal = 42
print(decimal)  # 输出: 42

# 二进制表示(以0b开头)
binary = 0b101010
print(binary)    # 输出: 42

# 八进制表示(以0o开头)
octal = 0o52
print(octal)     # 输出: 42

# 十六进制表示(以0x开头)
hexadecimal = 0x2A
print(hexadecimal)  # 输出: 42

大整数处理

Python可以处理任意大小的整数,不会溢出:

# 大整数计算
big_number = 10**100  # 10的100次方
print(big_number)
# 输出: 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

factorial = 1
for i in range(1, 51):
    factorial *= i

print("50的阶乘是:", factorial)
# 输出一个非常大的数字,不会溢出

2.3.2 浮点数类型(float)

浮点数用于表示实数:

# 浮点数表示
x = 3.14
y = -0.001
z = 2.0

# 科学计数法
scientific = 3.14e2  # 3.14 × 10²
print(scientific)    # 输出: 314.0

small = 1.23e-4     # 1.23 × 10⁻⁴
print(small)         # 输出: 0.000123

浮点数精度问题

由于二进制浮点数的表示方式,某些小数在计算机中无法精确表示:

# 浮点数精度问题
print(0.1 + 0.2)     # 输出: 0.30000000000000004
print(0.1 + 0.2 == 0.3)  # 输出: False

# 解决方法:使用decimal模块
from decimal import Decimal

print(Decimal('0.1') + Decimal('0.2'))  # 输出: 0.3
print(Decimal('0.1') + Decimal('0.2') == Decimal('0.3'))  # 输出: True

2.3.3 复数类型(complex)

复数由实部和虚部组成,虚部以j或J结尾:

# 复数表示
z1 = 2 + 3j
z2 = complex(2, 3)  # 另一种创建方式

print(z1)          # 输出: (2+3j)
print(z1 == z2)    # 输出: True

# 获取实部和虚部
print(z1.real)     # 输出: 2.0
print(z1.imag)     # 输出: 3.0

复数的基本操作

# 复数运算
z1 = 2 + 3j
z2 = 1 - 2j

print(z1 + z2)     # 输出: (3+1j)
print(z1 - z2)     # 输出: (1+5j)
print(z1 * z2)     # 输出: (8-1j)
print(z1 / z2)     # 输出: (-0.8+1.4j)

# 复数的共轭
print(z1.conjugate())  # 输出: (2-3j)

# 复数的模
import math
print(abs(z1))     # 输出: 3.605551275463989

2.3.4 数字类型之间的转换

# 整数转浮点数
print(float(42))    # 输出: 42.0

# 浮点数转整数(截断小数部分)
print(int(3.14))    # 输出: 3
print(int(-3.14))   # 输出: -3

# 整数或浮点数转复数
print(complex(2))       # 输出: (2+0j)
print(complex(2, 3))    # 输出: (2+3j)
print(complex(2.5, 1.5))  # 输出: (2.5+1.5j)

2.4 运算符与表达式

2.4.1 算术运算符

基本算术运算(+、-、*、/)

a = 10
b = 3

print(a + b)  # 加法,输出: 13
print(a - b)  # 减法,输出: 7
print(a * b)  # 乘法,输出: 30
print(a / b)  # 除法,输出: 3.3333333333333335(返回浮点数)

整除运算符(//)

整除运算符返回商的整数部分(向下取整):

print(10 // 3)   # 输出: 3
print(-10 // 3)  # 输出: -4(向下取整)

取模运算符(%)

取模运算符返回除法的余数:

print(10 % 3)   # 输出: 1
print(15 % 4)   # 输出: 3

# 判断奇偶性
print(10 % 2)   # 输出: 0(偶数)
print(11 % 2)   # 输出: 1(奇数)

幂运算符(**)

print(2 ** 3)   # 2的3次方,输出: 8
print(10 ** 2)  # 10的2次方,输出: 100
print(4 ** 0.5) # 4的平方根,输出: 2.0

2.4.2 比较运算符

比较运算符用于比较两个值,返回布尔值(True或False):

x = 10
y = 20

print(x == y)  # 等于,输出: False
print(x != y)  # 不等于,输出: True
print(x > y)   # 大于,输出: False
print(x < y)   # 小于,输出: True
print(x >= y)  # 大于等于,输出: False
print(x <= y)  # 小于等于,输出: True

2.4.3 逻辑运算符

and、or、not运算符

x = True
y = False

print(x and y)  # 逻辑与,输出: False
print(x or y)   # 逻辑或,输出: True
print(not x)    # 逻辑非,输出: False

# 在条件语句中使用
age = 25
income = 50000

if age > 18 and income > 30000:
    print("符合贷款条件")

if age < 18 or income < 10000:
    print("不符合贷款条件")

短路求值

Python的逻辑运算符使用短路求值,即如果第一个操作数已经能够确定结果,就不会计算第二个操作数:

# and的短路求值:如果第一个操作数为False,则不计算第二个操作数
x = False
y = print("计算y") or True  # 如果计算y,会打印"计算y"

result = x and y  # 由于x为False,y不会被计算
print(result)     # 输出: False

# or的短路求值:如果第一个操作数为True,则不计算第二个操作数
x = True
y = print("计算y") or False  # 如果计算y,会打印"计算y"

result = x or y   # 由于x为True,y不会被计算
print(result)     # 输出: True

2.4.4 位运算符

位运算符对整数的二进制表示进行操作:

a = 60  # 二进制: 0011 1100
b = 13  # 二进制: 0000 1101

# 按位与(&):对应位都为1时结果为1,否则为0
print(a & b)   # 输出: 12 (二进制: 0000 1100)

# 按位或(|):对应位有一个为1时结果为1,否则为0
print(a | b)   # 输出: 61 (二进制: 0011 1101)

# 按位异或(^):对应位不同时结果为1,相同为0
print(a ^ b)   # 输出: 49 (二进制: 0011 0001)

# 按位取反(~):0变1,1变0
print(~a)      # 输出: -61 (二进制: 1100 0011,带符号位)

# 左移(<<):所有位向左移动指定位数,右侧补0
print(a << 2)  # 输出: 240 (二进制: 1111 0000)

# 右移(>>):所有位向右移动指定位数,左侧补0(无符号数)或补符号位(有符号数)
print(a >> 2)  # 输出: 15 (二进制: 0000 1111)

2.4.5 赋值运算符

基本赋值(=)

x = 10  # 将10赋值给变量x

复合赋值(+=、-=、*=等)

x = 10

x += 5   # 等同于 x = x + 5,结果: 15
x -= 3   # 等同于 x = x - 3,结果: 12
x *= 2   # 等同于 x = x * 2,结果: 24
x /= 4   # 等同于 x = x / 4,结果: 6.0
x //= 2  # 等同于 x = x // 2,结果: 3.0
x %= 2   # 等同于 x = x % 2,结果: 1.0
x **= 3  # 等同于 x = x ** 3,结果: 1.0

# 位运算的复合赋值
y = 5
y &= 3   # 等同于 y = y & 3,结果: 1
y |= 4   # 等同于 y = y | 4,结果: 5
y ^= 2   # 等同于 y = y ^ 2,结果: 7
y <<= 1  # 等同于 y = y << 1,结果: 14
y >>= 2  # 等同于 y = y >> 2,结果: 3

2.4.6 成员运算符(in、not in)

成员运算符用于检查序列中是否存在指定的值:

fruits = ["apple", "banana", "cherry"]

print("apple" in fruits)       # 输出: True
print("orange" in fruits)      # 输出: False
print("orange" not in fruits)  # 输出: True

text = "Hello, Python!"
print("Python" in text)        # 输出: True
print("Java" in text)          # 输出: False

2.4.7 身份运算符(is、is not)

身份运算符用于比较两个对象是否是同一个对象(是否有相同的内存地址):

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a is b)     # 输出: False(a和b是不同的对象)
print(a is c)     # 输出: True(a和c引用同一个对象)
print(a == b)     # 输出: True(a和b的值相等)

# None的比较应该使用is
x = None
print(x is None)  # 输出: True(推荐的写法)
print(x == None)  # 输出: True(不推荐的写法)

2.4.8 运算符优先级

Python中的运算符有不同的优先级,决定了表达式中运算的执行顺序:

# 优先级示例
result = 2 + 3 * 4  # 乘法优先级高于加法
print(result)       # 输出: 14,而不是20

# 使用括号改变优先级
result = (2 + 3) * 4
print(result)       # 输出: 20

以下是Python运算符的优先级,从高到低排列:

  1. 括号 ()
  2. 幂运算 **
  3. 正负号 +x, -x
  4. 乘、除、整除、取模 *, /, //, %
  5. 加减 +, -
  6. 位移 <<, >>
  7. 按位与 &
  8. 按位异或 ^
  9. 按位或 |
  10. 比较运算符 ==, !=, >, >=, <, <=, is, is not, in, not in
  11. 逻辑非 not
  12. 逻辑与 and
  13. 逻辑或 or
  14. 条件表达式 if-else
  15. 赋值运算符 =, +=, -=

2.5 输入输出函数

2.5.1 print()函数详解

基本用法

# 打印单个值
print("Hello, Python!")

# 打印多个值
print("Name:", "Alice", "Age:", 30)

# 打印变量
name = "Bob"
age = 25
print(name, age)

参数详解(sep、end、file、flush)

# sep参数:指定值之间的分隔符,默认为空格
print("apple", "banana", "cherry", sep=", ")
# 输出: apple, banana, cherry

# end参数:指定输出结束后的字符,默认为换行符\n
print("Hello", end=" ")
print("World!")
# 输出: Hello World!

# file参数:指定输出的文件对象,默认为sys.stdout
with open("output.txt", "w") as f:
    print("This will be written to the file", file=f)

# flush参数:是否立即刷新输出缓冲区,默认为False
import time

for i in range(5):
    print(i, end=" ", flush=True)  # 立即显示,不等待缓冲区填满
    time.sleep(0.5)

格式化输出

# 使用%运算符格式化
name = "Alice"
age = 30
print("%s is %d years old." % (name, age))
# 输出: Alice is 30 years old.

# 使用str.format()方法
print("{} is {} years old.".format(name, age))
# 输出: Alice is 30 years old.

# 使用f-string(Python 3.6+)
print(f"{name} is {age} years old.")
# 输出: Alice is 30 years old.

2.5.2 input()函数详解

用户输入获取

# 基本用法
name = input("请输入您的名字: ")
print(f"您好,{name}!")

# 输入提示:请输入您的名字: Alice
# 输出: 您好,Alice!

输入数据的类型转换

input()函数始终返回字符串,需要根据需要进行类型转换:

# 获取整数输入
age = int(input("请输入您的年龄: "))
print(f"明年您将是{age + 1}岁")

# 获取浮点数输入
height = float(input("请输入您的身高(米): "))
print(f"您的身高是{height}米")

输入验证

# 简单的输入验证
while True:
    try:
        age = int(input("请输入您的年龄(1-120): "))
        if 1 <= age <= 120:
            break
        else:
            print("年龄必须在1到120之间,请重新输入")
    except ValueError:
        print("请输入有效的数字")

print(f"您的年龄是{age}岁")

2.5.3 格式化字符串

Python提供了多种字符串格式化方法:

%格式化

name = "Alice"
age = 30
salary = 50000.75

# 字符串格式化
print("%s is %d years old." % (name, age))
# 输出: Alice is 30 years old.

# 数字格式化
print("Salary: $%.2f" % salary)
# 输出: Salary: $50000.75

# 宽度和对齐
print("%10s" % name)      # 右对齐,宽度为10
# 输出: '     Alice'
print("%-10s" % name)     # 左对齐,宽度为10
# 输出: 'Alice     '

# 零填充
print("%05d" % age)
# 输出: 00030

str.format()方法

name = "Bob"
age = 25
salary = 45000.50

# 基本用法
print("{} is {} years old.".format(name, age))
# 输出: Bob is 25 years old.

# 使用索引
print("{1} is {0} years old.".format(age, name))
# 输出: Bob is 25 years old.

# 使用命名参数
print("{name} is {age} years old.".format(name=name, age=age))
# 输出: Bob is 25 years old.

# 数字格式化
print("Salary: ${:.2f}".format(salary))
# 输出: Salary: $45000.50

# 宽度和对齐
print("{:10}".format(name))      # 右对齐,宽度为10
# 输出: '       Bob'
print("{:<10}".format(name))     # 左对齐,宽度为10
# 输出: 'Bob       '
print("{:^10}".format(name))     # 居中对齐,宽度为10
# 输出: '   Bob    '

# 零填充
print("{:05d}".format(age))
# 输出: 00025

f-string(格式化字符串字面值)

f-string是Python 3.6引入的一种字符串格式化方法,语法简洁且性能更好:

name = "Charlie"
age = 35
salary = 60000.25

# 基本用法
print(f"{name} is {age} years old.")
# 输出: Charlie is 35 years old.

# 表达式计算
print(f"Next year, {name} will be {age + 1} years old.")
# 输出: Next year, Charlie will be 36 years old.

# 数字格式化
print(f"Salary: ${salary:.2f}")
# 输出: Salary: $60000.25

# 宽度和对齐
print(f"{name:10}")      # 右对齐,宽度为10
# 输出: '   Charlie'
print(f"{name:<10}")     # 左对齐,宽度为10
# 输出: 'Charlie   '
print(f"{name:^10}")     # 居中对齐,宽度为10
# 输出: ' Charlie  '

# 零填充
print(f"{age:05d}")
# 输出: 00035

# 千位分隔符
print(f"{1000000:,}")
# 输出: 1,000,000

2.6 注释与代码规范

2.6.1 注释的重要性

注释是程序中的非执行文本,用于解释代码的功能、逻辑和目的。良好的注释可以:

  • 提高代码的可读性和可维护性
  • 帮助其他开发者理解代码
  • 记录代码的设计决策和注意事项
  • 方便未来的代码修改和调试

2.6.2 单行注释(#)

# 这是一个单行注释
x = 10  # 这是行尾注释

# 多行单行注释
# 第一行
# 第二行
# 第三行

2.6.3 多行注释(三引号)

Python没有专门的多行注释语法,但可以使用三引号字符串作为多行注释:

"""
这是一个多行注释
可以跨越多行
不会被执行
"""

'''
这也是一个多行注释
使用单引号也可以
'''

2.6.4 文档字符串(docstring)

文档字符串是特殊的多行注释,用于为模块、类、函数等提供文档:

def calculate_area(radius):
    """
    计算圆的面积

    参数:
        radius (float): 圆的半径

    返回:
        float: 圆的面积
    """
    import math
    return math.pi * radius ** 2

# 访问文档字符串
print(calculate_area.__doc__)

2.6.5 代码规范(PEP 8)

PEP 8是Python官方的代码风格指南,提供了编写Python代码的规范。以下是一些重要的规范:

缩进规范

# 使用4个空格进行缩进(不要使用制表符)
def function():
    if True:
        print("正确的缩进")

命名规范

# 变量和函数名使用小写字母,单词之间用下划线连接
user_name = "Alice"

def calculate_average(numbers):
    return sum(numbers) / len(numbers)

# 类名使用驼峰命名法
class UserProfile:
    pass

# 常量使用全大写字母
MAX_CONNECTIONS = 100

空行使用

# 顶级函数和类定义之间空两行
def function1():
    pass


class MyClass:
    pass


# 方法定义之间空一行
class AnotherClass:
    def method1(self):
        pass

    def method2(self):
        pass

行长度限制

PEP 8建议每行代码不超过79个字符:

# 长字符串的换行
long_string = (
    "这是一个很长的字符串,需要跨越多行,"
    "可以使用括号来连接多个字符串。"
)

# 长表达式的换行
result = (value1 + value2 + value3 +
          value4 + value5 + value6)

# 长函数调用的换行
function_call(argument1, argument2,
              argument3, argument4)

2.6.6 代码可读性最佳实践

# 使用有意义的变量名
user_age = 25  # 好的命名
a = 25         # 不好的命名

# 避免魔法数字,使用命名常量
MAX_ATTEMPTS = 3
for attempt in range(MAX_ATTEMPTS):
    # 处理逻辑
    pass

# 使用空格增加可读性
x = (a + b) * (c + d)  # 好的写法
x=(a+b)*(c+d)          # 不好的写法

# 使用空行分隔逻辑块
def process_data(data):
    # 数据验证
    if not data:
        return None

    # 数据处理
    result = []
    for item in data:
        result.append(item * 2)

    # 返回结果
    return result

总结

本章介绍了Python的基础语法,包括变量与标识符、数据类型、运算符与表达式、输入输出函数以及注释与代码规范。掌握这些基础知识对于学习Python编程至关重要,它们是构建更复杂程序的基石。在接下来的章节中,我们将在这些基础上,进一步学习Python的控制流程、数据结构和函数等更高级的概念。

小夜