python基础语法
python 基础语法
match语句
def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
- 注意最后一个代码块:“变量名”
_
被作为 通配符 并必定会匹配成功。如果没有 case 匹配成功,则不会执行任何分支。
你可以用 |
(“或”)将多个字面值组合到一个模式中:
case 401 | 403 | 404:
return "Not allowed"
推导式
names=['gao','jia','xing','supershy']
#列表推导式
m=[name.upper() for name in names if len(name)>3]
print(m)
#字典推导式
dict1={key:len(key) for key in names}
print(dict1)
squ={x:x**2 for x in range(5)}
print(squ)
#集合推导式
set1={x**2 for x in range(5)}
print(set1)
set2={i for i in 'abcderf' if i not in 'abc'}
print(set2)
#元组推导式
tup1=(x for x in range(1,9))
print(tup1) #返回的是生成器对象
print(tuple(tup1)) #tuple()转换成元组值
迭代器
- 迭代器是python中最强大的功能之一,是访问集合序列的一种方式
- 迭代器对象是从集合的第一个元素开始访问,直到最后一个元素停止,迭代器只能往前不会后退
- 迭代器的两个基本方式iter()和next()
- 字符串、列表和元组对象都可用于迭代器
#迭代器
# list1=[1,2,3,4]
#iter()和next()的基本使用
# it=iter(list1)
# print(next(it))
# print(next(it))
# print(next(it))
#使用for循环遍历
# it=iter(list1)
# for i in it:
# print(i,end=',')
# #使用next()函数
# import sys
# it=iter(list1)
# while True:
# try:
# print(next(it))
# except StopIteration:
# sys.exit()
# class MyNumbers:
# def __iter__(self):
# self.a=1
# return self
# def __next__(self):
# x=self.a
# self.a+=1
# return x
# myclass=MyNumbers()
# myiter=iter(myclass)
# print(next(myiter))
# print(next(myiter))
# print(next(myiter))
class MyNumbers:
def __iter__(self):
self.a=1
return self
def __next__(self):
if self.a<=20:
x=self.a
self.a+=1
return x
else:
raise StopIteration
myclass=MyNumbers()
myiter=iter(myclass)
for i in myiter:
print(i,end=' ')
生成器yield
-
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。
调用一个生成器函数,返回的是一个迭代器对象。
def counter(n):
while n<10:
yield n
n+=1
gen=counter(0)
print(next(gen))
for i in gen:
print(i,end=' ')
import sys
def fibonacci(n):
a,b,counter=0,1,0
while True:
if counter>n:
return
yield a
a,b=b,a+b
counter+=1
f=fibonacci(10)
while True:
try:
print(next(f),end=' ')
except StopIteration:
sys.exit()
函数
特殊参数
-
强制位置参数
-
Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 和 f 要求为关键字形参:
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| 位置或关键字 |
| - 仅限关键字
-- 仅限位置
函数示例
请看下面的函数定义示例,注意 /
和 *
标记:
>>> def standard_arg(arg):
... print(arg)
...
>>> def pos_only_arg(arg, /):
... print(arg)
...
>>> def kwd_only_arg(*, arg):
... print(arg)
...
>>> def combined_example(pos_only, /, standard, *, kwd_only):
... print(pos_only, standard, kwd_only)
第一个函数定义 standard_arg
是最常见的形式,对调用方式没有任何限制,可以按位置也可以按关键字传递参数:
>>> standard_arg(2)
2
>>> standard_arg(arg=2)
2
第二个函数 pos_only_arg
的函数定义中有 /
,仅限使用位置形参:
>>> pos_only_arg(1)
1
>>> pos_only_arg(arg=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'
第三个函数 kwd_only_arg
如在函数定义中通过 *
所指明的那样只允许关键字参数。
>>> kwd_only_arg(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
>>> kwd_only_arg(arg=3)
3
最后一个函数在同一个函数定义中,使用了全部三种调用惯例:
>>> combined_example(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: combined_example() takes 2 positional arguments but 3 were given
>>> combined_example(1, 2, kwd_only=3)
1 2 3
>>> combined_example(1, standard=2, kwd_only=3)
1 2 3
>>> combined_example(pos_only=1, standard=2, kwd_only=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'
下面的函数定义中,kwds
把 name
当作键,因此,可能与位置参数 name
产生潜在冲突:
def foo(name, **kwds):
return 'name' in kwds
调用该函数不可能返回 True
,因为关键字 'name'
总与第一个形参绑定。例如:
>>> foo(1, **{'name': 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'
>>>
加上 /
(仅限位置参数)后,就可以了。此时,函数定义把 name
当作位置参数,'name'
也可以作为关键字参数的键:
>>> def foo(name, /, **kwds):
... return 'name' in kwds
...
>>> foo(1, **{'name': 2})
True
换句话说,仅限位置形参的名称可以在 **kwds
中使用,而不产生歧义。
使用切片副本作为函数实参传递与不使切片副本传参的区别
- 不使用副本传递形参:直接操作原始数据,适用于需要修改原始对象的场景。
- 使用副本传递形参:保护原始数据不被修改,适用于需要保留原始状态的场景。
- 根据具体需求选择合适的方式,并注意浅拷贝与深拷贝的区别。
#使用副本作为函数实参传递
def print_models(unprinted_designs,completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f"Printing model: {current_design}")
completed_models.append(current_design)
def show_completed_models(completed_models):
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
def show_unprinted_designs(unprinted_designs):
print("\n打印pop后的unprinted_designs:")
for unprinted_design in unprinted_designs:
print(unprinted_design)
unprinted_designs=['phone case','robot pendant']
completed_models=[]
print_models(unprinted_designs[:],completed_models)
show_completed_models(completed_models)
show_unprinted_designs(unprinted_designs)
--->输出:
Printing model: robot pendant
Printing model: phone case
The following models have been printed:
robot pendant
phone case
打印pop后的unprinted_designs:
phone case
robot pendant
#不使副本传参的区别
def print_models(unprinted_designs,completed_models):
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f"Printing model: {current_design}")
completed_models.append(current_design)
def show_completed_models(completed_models):
print("\nThe following models have been printed:")
for completed_model in completed_models:
print(completed_model)
def show_unprinted_designs(unprinted_designs):
print("\n打印pop后的unprinted_designs:")
for unprinted_design in unprinted_designs:
print(unprinted_design)
unprinted_designs=['phone case','robot pendant']
completed_models=[]
print_models(unprinted_designs,completed_models)
show_completed_models(completed_models)
show_unprinted_designs(unprinted_designs)
--->输出:
Printing model: robot pendant
Printing model: phone case
The following models have been printed:
robot pendant
phone case
打印pop后的unprinted_designs:
模块创建及调用方式
创建模块
--->创建一个以.py结尾的文件,pizza.py内容如下:
def make_pizza(size,*toppings):
print(f"做一个 {size}寸的pizza,选放的调料有:")
for topping in toppings:
print(f"- {topping}")
使用创建的模块
方式一:直接导入整体模块
import pizza
pizza.make_pizza(16,'正常')
pizza.make_pizza(12,'加麻','加辣','多放芝士')
方式二:导入模块中的某个功能
from pizza import make_pizza
#直接使用模块的功能函数即可不用点号调用
make_pizza(16,'正常')
make_pizza(12,'加麻','加辣','多放芝士')
方式三:给模块功能起别名方式调用
from pizza import make_pizza as mp
mp(16,'正常')
mp(12,'加麻','加辣','多放芝士')
方式四:直接给模块起别名
import pizza as pz
pz.make_pizza(16,'正常')
pz.make_pizza(12,'加麻','加辣','多放芝士')
方式五:直接使用模块的所有功能
from pizza import *
make_pizza(16,'正常')
make_pizza(12,'加麻','加辣','多放芝士')
内置函数
lambda函数
- lambda 函数通常与内置函数如 map()、filter() 和 reduce() 一起使用,以便在集合上执行操作。
x = lambda a, b : a * b
print(x(5, 6))
map()
-
map()
用于将一个函数应用到可迭代对象(如列表、元组等)的每个元素上,然后返回一个包含结果的新可迭代对象。这是一种非常有效的方式来对数据进行转换。 -
map()
函数的基本语法如下:map(function, iterable, ...)
function
:要应用于可迭代对象的函数。iterable
:要进行映射操作的可迭代对象。
map()
函数可以接受多个可迭代对象,但每个可迭代对象的元素数量必须一致。它将function
应用于可迭代对象的对应元素,并返回一个迭代器,其中包含了所有映射后的结果。
words=["gao","jia","xing"]
a=list(map(str.title,words))
print(a)
numbers1=[1,2,3,4]
numbers2=[11,22,33,44]
b=list(map(lambda x,y:x*y,numbers1,numbers2))
print(b)
filter()
-
filter()
用于筛选可迭代对象中满足指定条件的元素,然后返回一个包含筛选结果的新可迭代对象。 -
filter()
函数的基本语法如下:filter(function, iterable)
function
:用于筛选元素的函数,该函数返回True
或False
。iterable
:要进行筛选操作的可迭代对象。
filter()
函数将function
应用于iterable
中的每个元素,并保留那些使function
返回True
的元素,生成一个包含筛选结果的迭代器。
numbers=[1,2,3,4,5,6,7,8]
a=list(filter(lambda x:x%2==0,numbers))
print(a)
words=['gao','jia','xing','supershy']
b=list(filter(lambda x: len(x)>5,words))
print(b)
reduce()
-
reduce()
用于对可迭代对象中的元素进行累积操作,从左到右依次应用指定的函数,将结果汇总为一个值。这在某些情况下非常有用,例如计算累积值或查找最大/最小值。 -
reduce()
函数的基本语法如下:functools.reduce(function, iterable[, initializer])
function
:用于累积操作的函数,该函数接受两个参数,并返回一个结果。iterable
:要进行累积操作的可迭代对象。initializer
(可选):累积的初始值。
reduce()
函数将function
应用于iterable
中的元素,从左到右依次累积,将结果传递给下一个元素。如果提供了
initializer
,它将作为累积的初始值。否则,iterable
的第一个元素将作为初始值。
from functools import reduce
#计算列表中元素的累积
numbers1=[1,2,3,4,5]
a=reduce(lambda x,y:x*y,numbers1)
print(a)
#找出列表中元素的最大值
numbers2=[22,44,11,66,88,3,4]
b=reduce(lambda x,y: x if x>y else y,numbers2)
print(b)
sum() 汇总计算
list1 = [1,2,3,4]
a = sum(list1)
print(a)
round() 将结果四舍五入
from math import pi
[str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
装饰器
一、装饰器的核心概念
-
函数是一等公民
Python中函数是对象,可以被赋值给变量、作为参数传递或作为返回值。例如:def greet(name): return f"Hello, {name}!" func = greet # 函数赋值给变量 print(func("Alice")) # 调用函数对象
-
闭包(Closure)
内部函数可以访问外部函数的变量,即使外部函数已执行完毕:def outer(msg): def inner(): print(msg) # 引用外部函数的变量msg return inner closure = outer("Hello") closure() # 输出: Hello
二、装饰器的基本结构
装饰器本质是一个接受函数作为参数,并返回新函数的高阶函数:
def simple_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@simple_decorator # 语法糖,等同于 my_func = simple_decorator(my_func)
def my_func():
print("Function is called")
my_func()
# 输出:
# Before function call
# Function is called
# After function call
三、处理带参数的函数
若被装饰的函数有参数,需在内部函数中使用*args
和**kwargs
接收任意参数:
def decorator_with_args(func):
def wrapper(*args, **kwargs):
print("Decorator: Processing arguments")
return func(*args, **kwargs)
return wrapper
@decorator_with_args
def add(a, b):
return a + b
print(add(3, 5)) # 输出: Decorator: Processing arguments → 8
四、带参数的装饰器
若装饰器本身需要参数,需再嵌套一层函数:
def repeat(n_times): # 外层接收装饰器参数
def actual_decorator(func): # 中层接收被装饰函数
def wrapper(*args, **kwargs): # 内层处理函数调用
result = None
for _ in range(n_times):
result = func(*args, **kwargs)
return result
return wrapper
return actual_decorator
@repeat(n_times=3)
def say_hello():
print("Hello!")
say_hello()
# 输出三次: Hello!
五、保留原函数的元信息
使用functools.wraps
保留原函数的__name__
和文档字符串:
from functools import wraps
def preserve_metadata(func):
@wraps(func) # 关键:复制原函数信息到wrapper
def wrapper(*args, **kwargs):
"""Wrapper function's docstring."""
return func(*args, **kwargs)
return wrapper
@preserve_metadata
def sample():
"""Original docstring."""
pass
print(sample.__name__) # 输出: sample
print(sample.__doc__) # 输出: Original docstring.
六、类装饰器
通过实现__call__
方法让类的实例像函数一样被调用:
class ClassDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Class decorator: Before call")
result = self.func(*args, **kwargs)
print("Class decorator: After call")
return result
@ClassDecorator
def my_function():
print("Function execution")
my_function()
# 输出:
# Class decorator: Before call
# Function execution
# Class decorator: After call
七、装饰器的常见应用场景
- 日志记录:自动记录函数调用和参数。
- 性能测试:测量函数执行时间。
- 权限校验:检查用户权限再执行函数。
- 缓存(如
functools.lru_cache
):存储函数结果避免重复计算。
八、总结
- 装饰器的本质:通过闭包和高阶函数实现函数行为的动态修改。
- 关键点:理解
@
语法糖的等价替换、参数传递的层级、元信息保留。 - 适用场景:代码复用、AOP(面向切面编程)、增强函数功能。
通过灵活运用装饰器,可以大幅提升代码的简洁性和可维护性。
类
- 根据类来创建对象称为实例化,这让我们能够使用类的实例,例如my_dog=Dog('xiaobai',6) my_dog为实例
- 类中的函数称为方法
- __init__()是一个特殊的方法,每当运行类时python都会自动调用它
- 类中以self.为前缀的变量可以供类中所有方法使用,例如self.name=name 目的是将name实参传递给name变量,像这样可以通过实例访问的变量称为属性,调用方式my_dog.name
创建和使用类
- 创建一个小狗类Dog----它表示的不是特定的小狗,而是任意小狗
- 对于大多数宠物狗它们都有名字和年龄,还会坐下和打滚,大多数小狗都具备这两项信息(名字和年龄)和两种行为(坐下和打滚),Dog类将包含他们
class Dog:
"""一次模拟小狗的简单尝试"""
def __init__(self,name,age,*args):
"""初始化属性 name和age"""
self.name = name
self.age = age
self.foods = args
def sit(self):
"""模拟小狗收到命令后坐下"""
print(f"{self.name} 现在立刻坐下!!!")
def roll_over(self):
"""模拟小狗收到命令后打滚"""
print(f"{self.name} 现在立刻打滚!!!")
my_dog = Dog('xiaobai',6,'香肠','牛肉')
print(f'我的小狗的名字:{my_dog.name}')
print(f'我的小小狗的年龄:{my_dog.age}')
print(f'{my_dog.name} 爱吃的食物有:{my_dog.foods}')
my_dog.sit()
my_dog.roll_over()
your_dog=Dog('tudou',3,)
print(f'你的小狗的名字:{your_dog.name}')
print(f'你的小小狗的年龄:{your_dog.age}')
your_dog.sit()
your_dog.roll_over()
修改属性值的方式
一个模拟汽车的类
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
"""初始化汽车属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_describe_name(self):
"""返回描述信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def read_odometer(self):
"""打印出汽车的里程表英里数"""
print(f"该车的里程表: {self.odometer_reading}英里")
my_new_car = Car('china','小米','2025')
print(my_new_car.get_describe_name())
my_new_car.read_odometer()
1.直接通过实例修改属性值
my_new_car.odometer_reading = 20
my_new_car.read_odometer()
2.通过方法修改属性的值
def update_odometer(self,mileage):
"""将里程表设置成指定的值"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("不能回调英里数")
my_new_car.update_odometer(50)
my_new_car.read_odometer()
3.通过方法让属性的值传递
def increment_odometer(self,miles):
"""让里程表读书增加指定的量"""
if miles >=0:
self.odometer_reading += miles
else:
print("增加里程表英里数不能为负数")
my_new_car = Car('china','小米','2024')
print(my_new_car.get_describe_name())
my_new_car.update_odometer(50)
my_new_car.read_odometer()
my_new_car.increment_odometer(20)
my_new_car.read_odometer()
继承
- 当编写类时,并非总是从头开始,如果要编写的类是一个既有的类的特殊属性,可以使用继承
- 当一个类继承另一个类时,将自动获取后者的所有属性和方法,原有的类称为父类,而新的类称为子类
- 子类不仅继承了父类的所有属性和方法,也还可以定义自己的属性和方法
- 创建子类时,父类必须包含在该文件中且必须在子类的前面
- 定义子类时,必须在括号内指定父类名称
- super()是一个特殊的函数,让你能够调用父类的方法,这行代码让python调用Car类的__init__()方法,从而让ElectricCar实例包含这个方法定义的所有属性。父类也成为超类(superclass),函数名super由此得名
class Car:
"""一次模拟汽车的简单尝试"""
def __init__(self,make,model,year):
"""初始化汽车属性"""
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_describe_name(self):
"""返回描述信息"""
long_name = f"{self.year} {self.make} {self.model}"
return long_name.title()
def update_odometer(self,mileage):
"""将里程表设置成指定的值"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("不能回调英里数")
def read_odometer(self):
"""打印出汽车的里程表英里数"""
print(f"该车的里程表: {self.odometer_reading}英里")
def increment_odometer(self,miles):
"""让里程表读数增加指定的量"""
if miles >=0:
self.odometer_reading += miles
else:
print("增加里程表英里数不能为负数")
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
super().__init__(make, model, year)
my_leaf = ElectricCar('china','爱玛','2012')
print(my_leaf.get_describe_name())
重写
重写父类中的方法
- 如果父类中的一些方法不能满足子类的需求,就可以用下面的方法重写:
- 在子类中定义一个与重写的父类方法同名的方法。
- 这样python将忽略这个父类的方法,你只需关注子类中定义的相应方法
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
-->输出:
调用子类方法
调用父类方法
重构
很多时候虽然代码能够正确地运行,但还可以将其划分为一系列完成具体工作的函数来进行改进。这样的过程称为重构。重构让代码更清晰、更易于理解、更容易扩展。
接下来重构以下代码:
#!/usr/bin/python3
#_*_coding:utf-8_*_
from pathlib import Path
import json
path = Path('username.json')
if path.exists():
contents = path.read_text()
username = json.loads(contents)
print(f"您好 {username}")
else:
username = input("输入你的名字: ")
contents = json.dumps(username)
path.write_text(contents)
print(f"您好 {username}")
重构后:
#!/usr/bin/python3
#_*_coding:utf-8_*_
from pathlib import Path
import json
def greet_user():
"""问候其名字"""
path = Path('username.json')
if path.exists():
contents = path.read_text()
username = json.loads(contents)
print(f"您好 {username}")
else:
username = input("输入你的名字: ")
contents = json.dumps(username)
path.write_text(contents)
print(f"您好 {username}")
greet_user()
接下来再次重构greet_user()函数,不让他执行那么多的功能:
#!/usr/bin/python3
#_*_coding:utf-8_*_
from pathlib import Path
import json
def get_stored_username(path):
"""如果存储了用户名则使用它"""
if path.exists():
contents = path.read_text()
username = json.loads(contents)
return username
else:
return None
def greet_user():
"""问候其名字"""
path = Path('username.json')
username = get_stored_username(path)
if username:
print(f"您好 {username}")
else:
username = input("输入你的名字: ")
contents = json.dumps(username)
path.write_text(contents)
print(f"您好 {username}")
greet_user()
还可以在细分greet_user()函数功能:
#!/usr/bin/python3
#_*_coding:utf-8_*_
from pathlib import Path
import json
def get_stored_username(path):
"""如果存储了用户名则使用它"""
if path.exists():
contents = path.read_text()
username = json.loads(contents)
return username
else:
return None
def get_new_username(path):
"""提示输入用户名"""
username = input("输入你的名字: ")
contents = json.dumps(username)
path.write_text(contents)
return username
def greet_user():
"""问候其名字"""
path = Path('username.json')
username = get_stored_username(path)
if username:
print(f"您好 {username}")
else:
username = get_new_username(path)
print(f"您好 {username}")
greet_user()
类的私有属性
- _ _private_attrs,python中以两个下划线开头声明该属性为私有,不能被类的外部调用或直接访问
#!/usr/bin/python3
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
-->输出:
1
2
2
Traceback (most recent call last):
File "test.py", line 16, in <module>
print (counter.__secretCount) # 报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通