Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
除了初始化,dict 可以通过 key 放入 :
d["Dora"] = 5
print(d["Dora"])
也可以通过 dict()
关键字加上关键字参数的方式创建:
d1: dict[str, str] = dict(mike = "boy", jack = "boy", dora = "girl")
print(d1)
一个 key 只能对应一个 value,key 不存在,dict 会报错。
通过 in
可判断 dict 中是否有 key 。
通过 get()
方法获取 value,如果 key 不存在,将返回 None,也可以自己指定 value。
删除一个键值对,使用 pop(key)
方法。
dict 特点:
- 查找和插入速度极快。
- 占用大量内存,内存浪费多。
list:
- 查找和插入的成本随着元素的增加而增加。
- 占用空间小,浪费内存很少。
注意:dict 的 key 必须是不可变对象(通过 key 计算位置的算法是哈希算法), 如 list 不可以作为 key。
是一组 key 的集合,key 不能重复。
创建 key,需要提供一个 list 作为输入集合。
重复元素会被自动过滤。
add(key)
方法添加元素到 set()
中。
remove(key)
方法删除元素。
set 可以进行交集、并集等操作。
set 内部元素同样需要保证是不可变元素。
不可变对象调用对象自身的任意方法,也不会改变对象自身内容。相反,这些方法会 创建新的对象并返回,这样就保证了不可变对象本身永远不可变。
不变对象有:None
、str
等。
函数是最基本的一种计算过程抽象的方式。
可以在交互式命令行中使用 help(函数名)
函数查看函数的帮助信息。
Python 中,函数名其实就是指向一个函数对象的引用。
dir(__builtins__)
查看 Python 内建函数。
Python 内置常用函数包括数据类型转换函数。
int()
转换为整数。float()
转换为浮点数。str()
转换为字符串。bool()
转换为布尔型变量。hex()
将十进制整数转换为十六进制整数。
定义函数格式:
def 函数名字(函数参数):
函数体
return 返回值
定义什么都不做的空函数,用 pass
语句。
可以用 isinstance()
进行参数检查。
if not isinstance(x, (int, float)):
raise TypeError("bad operand type")
函数可以返回多个值(实际是返回一个 tuple)。
默认参数
可以给参数设置默认值。
函数参数默认值默认参数要在后,不能放在非默认参数前面。
当不按顺序提供默认参数时,需要显式写出参数名,如:
def func(x: int, y: int, z: int = 3) -> int:
return x + y + z
from typing import NoReturn
def main() -> NoReturn:
print(func(y = 2, x = 1))
while True:
pass
定义参数时要注意:默认参数要指向不变对象。
可变参数
函数的参数可以是不确定的。
利用 tuple 实现的例子:
def calc(numbers: tuple[int, ...]) -> int:
sum = 0
for n in numbers:
sum: int = sum + n * n
return sum
calc((1,3))
但是这样,调用函数的时候,需要组装出一个 tuple。
可变参数示例:
def calc(*numbers: int) -> int:
sum = 0
for i in numbers:
sum = sum + n * n
return sum
calc(1,3)
nums :tuple[int, ...] = [1, 2, 3]
calc(*nums)
关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。 而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动 组装为一个dict。
注意:**extra
表示把extra这个dict的所有key-value用关键字参数传入到函数的**kw
参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到
函数外的extra。
命名关键字参数
可以利用命名关键字参数限制关键字参数的名字:
# 只接受 city 和 job 作为关键字参数。
def person(name: str, age: int, *, city, job):
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer')
命名关键字参数需要一个 *
特殊分隔符, *
后面的参数被视为命名关键字参数。
如果参数中已经有一个可变参数,后面跟着的命名关键字参数就不再需要 *
分隔符。
def person(name: str, age: int, *args: int, city, job) -> None:
print(name, age, args, city, job)
命名关键字必须传入参数名,可以有缺省值。
对于任意函数,都可以通过 func(*args, **kw)
的形式调用,无论它的参数是怎么
定义的。
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
args = (1,2,3,4)
kw = {"d":9, "e":10, "f": 3}
f1(*args, **kw)
f2(*args, **kw)
递归函数
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。