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))

 



posted @ 2019-03-15 13:54  bj我心飞翔  阅读(97)  评论(0)    收藏  举报