python 语法笔记
Quote
笔记、示例来自廖雪峰的python教程
补漏一些不熟悉的语法
函数
函数的参数
可变参数
在参数前面加上*,参数numbers接收到的是一个tuple,调用该函数时可以传入任意个参数(包括0个参数)
如果已经有一个list或tuple,该怎么传进去呢?
*nums代表把nums这个list的所有元素作为可变参数传进去
关键字参数
上面的可变参数允许传入0个或任意个参数,在调用时自动组装成一个tuple
而关键字参数运行传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
调用该函数时可以只传入必选参数
也可以传入任意个数的关键字参数
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
dict再传进去,在前面加上**,类似前面的*numbers
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra表示将extra传入**kw,kw将获得一个dict,这个dict是extra的一份拷贝
命名关键字参数
传入关键字参数后,我们想在函数内检查是否有city和job参数
def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。
调用方式:
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
参数组合
在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
高级特性
列表生成式
还可以两层循环
用例: 列出当前目录下所有的文件和目录名
if...else 的用法
函数式编程
高阶函数
map
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
filter
实例:埃氏素数筛
# 先构造一个从3开始的奇数序列
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
# 这是一个生成器,且是一个无限序列
# 然后定义一个筛选函数
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter()
while True:
n = next(it)
yield n
it = filter(_not_divisible(n), it)
# 打印100以内的素数
for n in primes():
if n < 100:
print(n)
else:
break
装饰器
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return wrapper
@log
def now():
print('2026-3-16')
# >>> now()
# call now():
# 2024-6-1
@log放到now()定义处相当于:
模块化编程
__init__.py的作用
特性:在import一个package后,就会执行这个package里的__init__.py
所以应该往__init__.py里放什么东西?
-
包的初始化
-
管理包的接口
相对导入
运行start.py会报错,因为 import 模块的搜寻路径是根据sys.path的列表来的,而sys.path内是当前工作目录,标准库和第三方库的路径,如果运行start.py就会找不到moduleB
解决办法:
A: 把路径append到sys.path
但这样不优雅,且文件夹名改变后就要修改
B: 改为相对导入
相对导入必须以from开头
但相对导入也有坑
直接运行相对导入的文件时(也就是这里的moduleA.py),不是以sys.path为搜寻路径,而是从module的__package__中寻找,而当一个文件作为最开始运行的脚步,他的__package__为None
所以一个文件使用了相对导入后,就不该直接运行改文件,而是在包外面新建一个文件来启动
然后就可以在main.py里 import x 了
有时可以写from packageA import *,*代表所有,这个所有并非指所有变量,而是通过对应__init__.py里的__all__定义的
- 包的信息
__version__, __author__这类