python-python基础4
本节内容:
- 字符编码
- 函数与函数式编程
- 递归
字符编码
关于字符编码:
- python 3里默认是unicode编码
- unicode 分为 utf-32(占4个字节),utf-16(占两个字节),utf-8(占1-4个字节), so utf-16就是现在最常用的unicode版本, 不过在文件里存的还是utf-8,因为utf8省空间
- 在py3中encode,在转码的同时还会把string 变成bytes类型,decode在解码的同时还会把bytes变回string

import sys print(sys.getdefaultencoding()) #获取默认字符集
函数与函数式编程
函数初体验:
import time def logger(): time_format = '%Y-%m-%d %X' time_current = time.strftime(time_format) with open('test.log','a+') as fp: fp.write('%s open a file\n' % time_current) def test1(): logger() print('this is in test1') time.sleep(1) def test2(): logger() print('this is in test2') time.sleep(1) def test3(): logger() print('this is in test3') test1() test2() test3()
从上面的代码可以看出函数的有点:
1. 代码可复用
2. 保持一致性
3. 易扩展
函数返回值
def test1(): #定义一个函数 print('in the test1') return 0 #函数结束,返回0。如果不显式定义返回值,则返回None x = test1() # 用x接收test1函数的返回值 print(x) # 查看test1函数的返回值
关于返回值:
python里函数的返回值可以是任何类型,也可以是多个返回值:
def test1(): return 1,'hello',['Jason','Zhuo'],{'name':'zhuo'}
上面这段代码返回多个值,执行结果是:
(1, 'hello', ['Jason', 'Zhuo'], {'name': 'zhuo'})
这其实就是返回一个元组。
总结:
返回值数=0: 返回None
返回值数=1:返回对应的值
返回值数>1:返回一个元组
函数调用
1. 位置参数(不识别参数名,按输入顺序传参,必须一对一):
def test(x,y): print(x) print(y) test(1,2)
2. 关键字参数(无需按顺序传值,只需按照参数名赋值即可。即关键字参数不关心传入顺序):
def test(x,y): print(x) print(y) test(x=2,y=1)
# test(3,y=2) # 关键字调用和位置调用同时出现时,关键字参数不能写在位置参数之前
# test(x=2,3) # 会报错
再来一个例子:
def test(x,y,z): #关键字参数不能写在位置参数之前
print(x)
print(y)
print(z)
test(1,z=2,y=3)
3. 默认参数
def test(x,y=2): print(x) print(y) test(1,3)
test(1)
默认参数特点:
调用函数的时候,默认参数可以不用传递。
4. 参数组(非固定参数)
位置参数、关键字参数和默认参数都有一个特点就是在调用的时候,传参个数不能大于定义的参数个数。
def test(*args): # 定义不定长参数个数的关键标志”*“, *args接受N个位置参数,转换成元组的方式 print(args) test(1,2,3,4) test(1,2,3,4,5,6) test(*[6,7,8,9])
##############################
# 结合位置参数的一个例子:
##############################
def test(x,*args):
print(x)
print(args)
test(1,2,3,4)
test(1,2,3,4,5,6)
test(*[6,7,8,9])
def test(**kwargs): # **kwargs 接收N个关键字参数转换成字典的形式 print(kwargs) test(name='Jason', age=8, sex='M') test(**{'name':'zhuo','age':8})
def test(name,**kwargs): #和位置参数结合 print(name) print(kwargs) test(name='Jason', age=8, sex='M')
def test(name,age=8,**kwargs): #和默认参数结合.参数组只能写到最后 print(name) print(age) print(kwargs) test('zhuo',sex='m',num=3)
局部变量
home = 'beijing'
def change_name(name):
global home
print("before change:", name)
name = 'Jason zhuo' # 局部变量只在函数里生效,生命周期随着函数而存在
print('after change:',name)
home = 'shandong'
# 下面这种方式并不能改变name的值
name = 'wukong'
change_name(name)
print("out func: name= ",name)
print(home)
# output:
before change: wukong
after change: Jason zhuo
out func: name= wukong
shandong
在上面的例子中,全局有个name变量,函数内也有个name变量,在函数内的name只能在函数中有效,所以在函数中打印name值可以是‘jason zhuo’,函数调用完成后,函数里的name不在有效,所以,函数调用完成后,打印name值,结果是‘悟空’。如果想在函数内修改全局变量的值,需要像home变量一样,在函数内生命global,这样修改就是对全局变量的修改。
上面这个例子是在函数中修改变量(字符串,当然也可以是整型、浮点型),这些变量是不能在函数中被修改的,那么如果是列表或字典是不是可以修改呢,我们试一下:
names = ['wukong','bajie','wujing'] def change_name(): names[0] = 'meihouwang' print(names) change_name() print('out of func: ',names) # output: ['meihouwang', 'bajie', 'wujing'] out of func: ['meihouwang', 'bajie', 'wujing']
通过上面的输出我们可以看到,列表的项在函数中的修改,是针对全局变量的修改。把列表换成字典以同样的方式修改字典的value得到的结果也是这样。所以,我们得出结论: 对于全局变量,除了整型、浮点型、字符串不能在函数中修改以外,列表、字典都是可以在函数中修改的。
递归
一个函数,在函数内部调用自己,这个函数就是递归函数
def calc(n): print(n) if n/2 >= 1: return calc(n/2) print('exit,n= ',n) calc(10)
输出:
10
5.0
2.5
1.25
exit,n= 1.25
递归需要注意的几点:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应该有所减少
3. 递归效率不高(递归过程就是一个不断的压栈过程),递归次数过多会导致栈溢出
高阶函数
高阶函数: 把一个函数作为另外一个函数的参数,这个以函数作为参数的函数就是高阶函数
def add(a,b,f): return f(a) + f(b) print(add(2,-6,abs))

浙公网安备 33010602011771号