if语句

1
2
3
4
5
6
7
8
9
10
11
12
x = int(input("Please enter an integer: "))

if x < 0:
x = 0
print('Negative changed to zero')
elif x == 0: # elif 时else if 的缩写
print('Zero')
elif x == 1:
print('Single')
else:
print('More')

条件控制

innot in 用于执行确定一个值是否存在(或不存在)于某个容器

isis not 用于比较两个对象是否是同一个对象

not取反

or and是短路运算符

:= 海象运算符用于在表达式中赋值

比较操作支持链式操作。例如,a < b == c 校验 a 是否小于 b,且 b 是否等于 c

1
2
3
4
5
6
7
(1, 2, 3)              < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

循环语句

  • break跳出最近一层循环
  • continue跳出本次循环
1
2
3
words = ['cat', 'window', 'defenestrate']
for w in words:
print(w, len(w))
1
2
3
flag = 1
while flag: print ('欢迎访问菜鸟教程!')
# while 循环体中只有一条语句,你可以将该语句与 while 写在同一行中,

循环语句可以有 else 子句

  • for 循环中,else 子句会在循环成功结束最后一次迭代之后执行。
  • while循环中,它会在循环条件变为假值后执行。
  • 但循环被 break 终止时不执行。
1
2
3
4
for i in 'makana':
if i == 'a':break
print(i)
else:print("yeselse") #break后else不会执行

循环的技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
dic = {'name': 'Alice', 'age': 17}

# 迭代key
for key in dic:
print(f'{key} {dic[key]}')

# 迭代values
for value in dic.values():
print(value)

# 同时迭代
for k, v in dic.items():
print(k, v)
1
2
3
4
5
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
# 0 tic
# 1 tac
# 2 toe
1
2
3
4
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
1
2
for i in reversed(range(1, 10, 2)):
print(i)
1
2
3
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for i in sorted(basket):
print(i)
1
2
3
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)

pass语句

pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句

1
2
3
4
5
6
7
8
while True:
pass # Busy-wait for keyboard interrupt (Ctrl+C)
# 创建一个最小的类
class MyEmptyClass:
pass
# 作函数或条件语句体的占位符
def initlog(*args):
pass # Remember to implement this!

match语句

1
2
3
4
5
6
7
8
9
10
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 匹配成功,则不会执行任何分支

类的部分未学习

1
2
3
4
5
6
7
8
9
10
11
12
# point is an (x, y) tuple
match point:
case (0, 0):
print("Origin")
case (0, y):
print(f"Y={y}")
case (x, 0):
print(f"X={x}")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a point")

case添加 if 子句,称为“约束项”

  • 如果约束项为假值,则 match 将继续尝试下一个 case 语句块
  • 值的捕获发生在约束项被求值之前
1
2
3
4
5
match point:
case Point(x, y) if x == y:
print(f"Y=X at {x}")
case Point(x, y):
print(f"Not on the diagonal")

函数

定义

1
2
3
4
5
6
7
8
9
10
11
def fib(n):  # return Fibonacci series up to n
"""Return a list containing the Fibonacci series up to n."""
result = []
a, b = 0, 1
while a < n:
result.append(a) # see below
a, b = b, a+b
return result

f100 = fib2(100) # call it
f100 # write the result

return 语句不带表达式参数时,返回 None。函数执行完毕退出也返回 None

参数

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数

  • / 前 仅限位置
  • *后 仅限关键字

参数检查

1
2
3
4
5
6
7
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x

默认参数

  • 在函数定义时计算,而非调用时。
  • 只计算一次
  • 建议使用不可变对象
  • 为可变对象时,会累积后续调用时传递的参数
1
2
3
4
5
6
7
8
9
10
def f(a, L=[]):
L.append(a)
return L

print(f(1))
print(f(2))
print(f(3))
# [1]
# [1, 2]
# [1, 2, 3]
1
2
3
4
5
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L

可变参数

  • *args 用于接受任意数量的位置参数,传入时会将多余的位置参数封装成一个元组。
  • **kwargs 用于接受任意数量的关键字参数,传入时会将多余的关键字参数封装成一个字典。
  • 同时使用 *args**kwargs,但 *args 必须在 **kwargs 之前定义
1
2
3
4
5
6
7
8
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n
return sum

lis = [1,2,3]
calc(*lis) # 解包调用
1
2
3
4
5
6
7
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)


extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, city=extra['city'], job=extra['job']) # 调用
person('Jack', 24, **extra) # 解包调用

命名关键字参数

  • 关键字参数调用时必须跟在位置参数后面
  • *后面的参数被视为命名关键字参数
1
2
3
4
5
def person(name, age, *, city, job):
print(name, age, city, job)

# 下列调用无效
parrot(city=5.0, 'Alice')
  • 已经有可变参数, 后面不用添加*
1
2
def person(name, age, *args, city, job):
print(name, age, args, city, job)

递归函数

  • 递归的深度到999,不会报错
1
2
3
4
def fact(n):
if n==1:
return 1
return n * fact(n - 1)

map/reduce

map用于将一个函数作用于一个序列,以此得到另一个序列

  • 结果是一个生成器
1
2
3
4
5
6
lis = [1,2,3]
def sqr(x):
return x*x

r = map(sqr,lis)
print(list(r))

reduce用于将一个函数依次作用于上次计算的结果和序列的下一个元素,以此得到最终结果

  • 函数必须有两个参数
1
2
3
4
5
def sqr(x,y):
return x*y

r = reduce(sqr,lis)
print(r)

PASS

filter/sorted

<font style="color:rgb(75, 85, 99);">filter()</font>将函数依次作用于每个元素,依据返回值是True还是False决定保留还是丢弃该元素

  • 返回生成器
1
2
3
4
5
def is_odd(s):
return s and s.strip()

r = filter(is_odd,['A', '', 'B', None, 'C', ' '])
print(list(r))
1
2
3
def is_palindrome(n):
s = str(n)
return s == s[::-1]

sorted()可以接收一个key函数来实现自定义的排序, 函数作用于所有元素

  • 要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True
  • 默认情况下,对字符串排序,是按照ASCII的大小比较的, 对字母排序可以用<font style="color:rgb(31, 41, 55);">lower()</font>
1
2
3
4
5
6
7
8
9
10
sorted([36, 5, -12, 9, -21]) 		  # 直接排序

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0].lower()
L2 = sorted(L, key=by_name)

def by_score(t):
return t[1]
L2 = sorted(L, key=by_score, reverse=True)

闭包

  1. 嵌套函数:闭包通常涉及到一个内部函数,该函数定义在另一个函数内部。
  2. 封闭的环境:内部函数能够访问外部函数的变量,即使外部函数已经执行完毕。
  3. 持久性:即使外部函数已经返回,内部函数依然可以使用外部函数的变量

inner_function 是一个闭包Closure

1
2
3
4
5
6
7
def outer_function(x):
def inner_function(y):
return x + y # inner_function 使用了外部函数的变量 x
return inner_function # 返回内部函数

closure = outer_function(10) # 调用外部函数,x 被绑定为 10
print(closure(5)) # 输出: 15,因为 x 是 10,y 是 5
  • 每次调用外部函数生成closure时, 都会生成全新的函数, 每个函数间不影响
  • 使用闭包时,对外层变量赋值前,需要先使用nonlocal声明
1
2
3
4
5
6
7
def createCounter():
x = 0
def counter():
nonlocal x
x +=1
return x
return counter

返回函数不要引用任何循环变量,或者后续会发生变化的变量。

1
2
3
4
5
6
7
8
9
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs

f1, f2, f3 = count() # 9 9 9
1
2
3
4
5
6
7
8
9
def count():
fs = []
for i in range(1, 4):
def f(i=i): # 将 i 作为默认参数传递
return i * i
fs.append(f)
return fs

f1, f2, f3 = count() # 1 4 9

Lambda表达式

lambda 关键字用于创建小巧的匿名函数。lambda a, b: a+b 函数返回两个参数的和

1
2
3
4
5
6
7
8
9
def make_incrementor(n):
return lambda x: x + n

f = make_incrementor(42)

f(0) # 42

f(1) # 43

1
2
3
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1])
pairs

装饰器

  • @functools.wraps(func)用来避免函数的__name__属性变成wrapper
1
2
3
4
5
6
def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
1
2
3
4
5
6
7
8
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

pass

偏函数

使用functools.partial可以创建一个新函数 固定住原函数的部分参数

1
2
int2 = functools.partial(int, base = 2)
print(int2('100'))
1
2
3
4
max2 = functools.partial(max, 10)
# 相当于
args = (10, 5, 6, 7)
max(*args)

其他

文档字符串

1
2
3
4
5
6
7
8
def my_function():
"""Do nothing, but document it.

No, really, it doesn't do anything.
"""
pass

print(my_function.__doc__)

函数注解

1
print(fib.__annotations__)     

PASS

编码风格

  • 缩进,用 4 个空格
  • 换行,一行不超过 79 个字符。
  • 用空行分隔函数和类,及函数内较大的代码块。
  • 最好把注释放到单独一行。
  • 使用文档字符串。
  • 运算符前后、逗号后要用空格,但不要直接在括号内使用: a = f(1, 2) + g(3, 4)
  • 类和函数的命名要一致;按惯例,命名类用 UpperCamelCase,命名函数与方法用 lowercase_with_underscores。命名方法中第一个参数总是用 self (类和方法详见 初探类)。