python基础再复盘
1. 命名 关键字 格式化输出 输入输出
变量的命名是非常讲究的,这对于代码的可读性非常重要,比如,我们记录 语文80分,数学90分,用代码表示
a1 = 80 # 不可取!因为下次你看到a1你根本不知道它是什么意思
a2 = 90
...........
chinese_score = 80 # 除了下划线模式,还是大驼峰小驼峰模式
math_score = 90 # chineseScore 小驼峰,开头小写后面大写;MathScore 大驼峰,单词首字大写,但这种特别容易混,大写可以代表类,不推荐大驼峰
python中一些具有特殊功能的标示符就是关键字,and
if
pirnt
lambda
之类的。
%d %s %f 称之为 格式化输出
>>>print('my math score is %d'%math_score )
my math score is 90
>>>print(11111\n22222) # \n 表示换行
11111
22222
>>>a = input("i love:")
i love:xiaohua
>>>print("who is %s"%a)
who is xiaohua
转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
函数
内置函数就是可以直接调用函数,比如abs
递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
我们来计算阶乘n! = 1 x 2 x 3 x ... x n
,用函数fact(n)
表示
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰
切片
>>>a = [1,2,3,4,5]
>>>a[::-1] # 表示所有的数,每隔-1取一个,所以就成倒叙排列
[5,4,3,2,1]
>>>a[:4:2] # 表示前4个数,每隔2个取一个,取第0个,取第三个,所以1,3
[1,3]
高阶函数
编写高阶函数,就是让函数的参数能够接收别的函数
闭包
注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。
另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()
才执行。我们来看一个例子:
def count(): # CCC
fs = []
for i in range(1, 4): # AAA
def f(): # BBB
return i*i # append进去的不是值,而是函数`f`,这种情况就会造成闭包!!!
fs.append(f) # 请注意,函数f并没有被立即执行,而是当成变量暂时搁置。这行是比AAA行缩进一次,所以它append对应的rang
return fs
# 首先要明确一点,变量都是引用的内存的一个对象,当程序进入循环,按道理说应该是返回1,4,9这样一个东西,但是,我们返回的是函数,且这个函数在返回时并没有执行,这就意味着i变量指向内存里的那个对象已经为3了,我们再次PRINT的时候,函数才执行得出结果,计算过程里i都为3,所以结果应该为9,9,9
f1, f2, f3 = count()
在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。
你可能认为调用f1()
,f2()
和f3()
结果应该是1,4,9,但实际结果是:
>>> f1()
9
>>> f2()
9
>>> f3()
9
关于闭包,我们再看这个例子:
def lazy_sum(*args): # 注意看缩进,确定每行代码的关系
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum # 注意⚠️,忽然明白了,这里return返回的是函数sum,不是一个值,所以最终出现无法打印结果的情况。
当我们调用lazy_sum()
时,返回的并不是求和结果,而是求和函数:
>>> haha = lazy_sum(1, 3, 5, 7, 9)
>>> haha
<function lazy_sum.<locals>.sum at 0x101c6ed90> # 这行表示结果是一个sum的求和函数,所以无法打印结果
>>>lazy_sum(1,2,3)
<function __main__.lazy_sum.<locals>.sum>
>>>lazy_sum(1,2,3)()
6
调用函数f
时,才真正计算求和的结果:
>>> haha()
25
在这个例子中,我们在函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
上述闭包例子我做了个对比:
def lazy_sum(*args): # 注意看缩进,确定每行代码的关系
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum()
>>> haha = lazy_sum(1, 3, 5, 7, 9)
>>> haha # 这里的haha就是一个值,所以直接出值
25
>>>haha() # 这里的haha其实就是个值int了,你再加( )当然报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
个人总结:闭包是什么?当你函数属于高阶函数,最终返回到第一层的函数的 就是内部的函数而不是一个值的时候,就会出现闭包。
filter
Python内建的filter()
函数用于过滤序列
例如,在一个list中,删掉偶数,只保留奇数,可以这么写:
def is_odd(n):
return n % 2 == 1 # 定义奇数
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 这里是保留奇数,is貌似起作用
# 结果: [1, 5, 9, 15]
把一个序列中的空字符串无效字符串删掉,可以这么写:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' '])) # 同上面格式相同,它却删除空,not 起作用,注意与上面的区别!
# 结果: ['A', 'B', 'C']
注意到filter()
函数返回的是一个Iterator
,也就是一个惰性序列,所以要强迫filter()
完成计算结果,需要用list()
函数获得所有结果并返回list。