# Python 字符串操作

## 学习目标
- 掌握字符串的索引、切片和常用方法
- 理解字符串的不可变性
- 熟练使用 f-string 和 format 进行格式化输出
- 学会字符串的编码与解码

---

## 一、字符串基础回顾

```python
# 字符串定义
s1 = '单引号字符串'
s2 = "双引号字符串"
s3 = '''多行
字符串'''
s4 = """也支持
双引号多行"""

# 字符串是不可变类型
s = "hello"
# s[0] = "H"   # TypeError: 'str' object does not support item assignment
```

---

## 二、字符串索引与切片

```python
text = "Python3"

# 索引（从 0 开始，支持负数）
print(text[0])     # P
print(text[-1])    # 3（最后一个字符）
print(text[-2])    # n（倒数第二个）

# 切片 [start:end:step]
print(text[0:6])     # Python
print(text[:6])      # Python（从头开始）
print(text[6:])      # 3（到末尾）
print(text[:])       # Python3（完整复制）
print(text[::2])     # Pto3（每隔一个）
print(text[::-1])    # 3nohtyP（反转）

# 负数步长
print(text[6:0:-1])  # 3nohty（从 6 倒到 1）
print(text[-3:])     # on3（最后三个字符）
```

---

## 三、字符串常用方法

### 3.1 大小写转换

```python
s = "Hello Python"

print(s.upper())           # HELLO PYTHON
print(s.lower())           # hello python
print(s.capitalize())      # Hello python（首字母大写）
print(s.title())           # Hello Python（每个单词首字母大写）
print(s.swapcase())        # hELLO pYTHON（大小写互换）
```

### 3.2 查找与替换

```python
text = "Python is great, Python is easy"

print(text.find("Python"))       # 0（首次出现位置，-1 表示未找到）
print(text.rfind("Python"))      # 18（最后一次出现位置）
print(text.index("great"))       # 10（类似 find，找不到会抛异常）
print(text.count("Python"))      # 2（出现次数）
print(text.replace("Python", "Java"))   # Java is great, Java is easy
print(text.replace("Python", "Java", 1)) # Java is great, Python is easy（只替换1次）
```

### 3.3 判断类方法

```python
print("abc".isalpha())       # True（全是字母）
print("123".isdigit())       # True（全是数字）
print("abc123".isalnum())    # True（字母或数字）
print("  ".isspace())        # True（全是空白）
print("Hello".istitle())     # True（标题格式）
print("ABC".isupper())       # True（全大写）
print("abc".islower())       # True（全小写）
print("123".isdecimal())     # True（十进制数字）
print("Ⅷ".isnumeric())       # True（包括罗马数字等）

# 开头结尾判断
print("hello.py".startswith("h"))    # True
print("hello.py".endswith(".py"))    # True
```

### 3.4 修剪与填充

```python
s = "  hello  world  "

print(s.strip())        # "hello  world"（去两端空白）
print(s.lstrip())       # "hello  world  "（去左端）
print(s.rstrip())       # "  hello  world"（去右端）

# 指定字符修剪
print("---hello---".strip("-"))   # hello

# 填充
print("42".zfill(5))            # 00042（左侧补零）
print("hi".center(10))          # "    hi    "（居中）
print("hi".center(10, "-"))     # "----hi----"
print("hi".ljust(10))           # "hi        "（左对齐）
print("hi".rjust(10))           # "        hi"（右对齐）
```

### 3.5 分割与拼接

```python
# split() 分割
text = "apple,banana,cherry"
print(text.split(","))          # ['apple', 'banana', 'cherry']
print(text.split(",", 1))       # ['apple', 'banana,cherry']（只分割1次）

# rsplit() 从右边分割
text = "a,b,c,d"
print(text.rsplit(",", 1))      # ['a,b,c', 'd']

# splitlines() 按行分割
lines = "line1\nline2\r\nline3"
print(lines.splitlines())       # ['line1', 'line2', 'line3']

# join() 拼接
fruits = ["apple", "banana", "cherry"]
print(", ".join(fruits))        # apple, banana, cherry
print("-".join("Python"))       # P-y-t-h-o-n
```

---

## 四、字符串格式化

### 4.1 f-string（推荐，Python 3.6+）

```python
name = "Alice"
age = 25
pi = 3.14159

# 基本用法
print(f"姓名: {name}, 年龄: {age}")

# 表达式
print(f"明年 {age + 1} 岁")
print(f"圆周率: {pi:.2f}")     # 3.14（保留两位小数）
print(f"百分比: {0.85:.1%}")   # 85.0%

# 对齐与填充
print(f"{name:>10}")          # "     Alice"（右对齐）
print(f"{name:<10}")          # "Alice     "（左对齐）
print(f"{name:^10}")          # "  Alice   "（居中）
print(f"{name:*^10}")         # "**Alice***"（居中，*填充）

# 数字格式化
num = 1234
print(f"{num:08d}")           # 00001234（补零）
print(f"{num:,}")             # 1,234（千分位）
print(f"{num:b}")             # 10011010010（二进制）
print(f"{num:x}")             # 4d2（十六进制）
print(f"{num:e}")             # 1.234000e+03（科学计数法）
```

### 4.2 format() 方法

```python
# 位置参数
print("{} 和 {}".format("苹果", "香蕉"))      # 苹果 和 香蕉
print("{1} 和 {0}".format("苹果", "香蕉"))    # 香蕉 和 苹果

# 关键字参数
print("姓名: {name}, 年龄: {age}".format(name="Bob", age=30))

# 字典解包
info = {"name": "Charlie", "age": 35}
print("姓名: {name}, 年龄: {age}".format(**info))
```

### 4.3 % 格式化（旧式，了解即可）

```python
name = "Alice"
age = 25

print("姓名: %s, 年龄: %d" % (name, age))
print("圆周率: %.2f" % 3.14159)
```

---

## 五、字符串编码与解码

```python
# 编码：str → bytes
s = "你好，Python"
utf8_bytes = s.encode("utf-8")
gbk_bytes = s.encode("gbk")

print(utf8_bytes)    # b'\xe4\xbd\xa0\xe5\xa5\xbd\xef\xbc\x8cPython'
print(gbk_bytes)     # b'\xc4\xe3\xba\xc3\xef\xbc\x8cPython'

# 解码：bytes → str
s1 = utf8_bytes.decode("utf-8")
s2 = gbk_bytes.decode("gbk")
print(s1)    # 你好，Python
print(s2)    # 你好，Python

# 处理编码错误
try:
    bad = b"\xff\xfe".decode("utf-8")
except UnicodeDecodeError:
    print("解码失败")

# 使用 errors 参数处理
bad_safe = b"\xff\xfe".decode("utf-8", errors="replace")
print(bad_safe)    # ��（用替换字符显示）
```

---

## 六、综合示例

```python
"""
文本处理工具：格式化报表
"""

data = [
    {"name": "Alice", "age": 25, "score": 92.5},
    {"name": "Bob", "age": 30, "score": 85.0},
    {"name": "Charlie", "age": 22, "score": 78.5},
]

# 打印表头
print("=" * 40)
print(f"{'姓名':^10} | {'年龄':^6} | {'成绩':^8}")
print("-" * 40)

# 打印数据
for item in data:
    print(f"{item['name']:^10} | {item['age']:^6} | {item['score']:^8.1f}")

print("=" * 40)

# 处理用户输入
text = input("\n请输入一段文字: ")
print(f"\n文字统计:")
print(f"  总字符数: {len(text)}")
print(f"  字母数: {sum(c.isalpha() for c in text)}")
print(f"  数字数: {sum(c.isdigit() for c in text)}")
print(f"  空格数: {sum(c.isspace() for c in text)}")
print(f"  单词数: {len(text.split())}")
print(f"  反转: {text[::-1]}")
```

---

## 小结

- 字符串是不可变对象，修改会创建新字符串
- 切片 `[start:end:step]` 功能强大，支持负数索引和步长
- 常用方法：`find()`、`replace()`、`split()`、`join()`、`strip()`
- **f-string** 是最推荐的格式化方式，简洁高效
- 字符串编码使用 `.encode()`，解码使用 `.decode()`

---

## 练习

1. 输入一个字符串，判断它是否为回文字符串（正读反读相同）。
2. 将字符串 `"hello world python"` 中每个单词的首字母大写。
3. 输入一个文件名，提取文件名和扩展名（如 `data.txt` → `data`, `txt`）。
4. 格式化输出一个九九乘法表，要求对齐美观。
5. 将一段英文文本中所有单词按字母顺序排序后输出。

