day3函数进阶

第1章 Day3函数

1.1 函数与过程的区别

为什么要有返回值

是因为下面的程序有可能要以这个函数的返回结果做不同的操作

#函数
def func1():
    '''testing1'''
   
print('in the func1')
    return 0
#过程
def func2():
    '''testing2'''
   
print('in the func2')

x=func1()
y=func2()
print('from func1 is %s' %x)
print('from func1 is %s' %y)
过程没定义返回值默认返回None

1.2 函数的作用

为了把相同逻辑的代码模块化 可以是程序变得简洁

提高代码利用率 避免相同代码多次出现

提高程序的可扩展性

import time
def logger():
    time_format = '%Y-%m-%d %X'
   
time_current = time.strftime(time_format)
    with open('a.txt','a+')as f:
        f.write('%s end action ' %time_current)
def test1():
    print('in the test1')
    logger()
def test2():
    print('in the test2')
    logger()
def test3():
    print('in the test3')
    logger()
test1()
test2()
test3()

1.3 返回值可以传多个参数

Python会把他当成一个元组返回

import time
def logger():
    time_format = '%Y-%m-%d %X'
   
time_current = time.strftime(time_format)
    with open('a.txt','a+')as f:
        f.write('%s end action ' %time_current)
def test1():
    print('in the test1')
    logger()
def test2():
    print('in the test2')
    logger()
def test3():
    print('in the test3')
    logger()
test1()
test2()
test3()
 
def test1():
    pass
def
test2():
    return 0
def test3():
    return 0,'hello',['a','b','c'],{'name':'lieying'}
x=test1()
y=test2()
z=test3()
print(x)
print(y)
print(z)
执行结果
 

None

0

(0, 'hello', ['a', 'b', 'c'], {'name': 'lieying'})

1.4 返回值可以是函数名

def test1():
    print('in the test1')
    pass
def
test2():
    print('in the test2')
    return 0
def test3():
    print('in the test3')
    #return 0,'hello',['a','b','c'],{'name':'lieying'}
   
return test2    #这里返回的将是test2函数的id
x=test1()
y=test2()
z=test3()
print(x)
print(y)
print(z)

返回结果

in the test1

in the test2

in the test3

None

0

<function test2 at 0x00000000031220D0>

1.5 形参

1.5.1 位置形参:按照从左到右顺序依次定义的参数 必须被传参多一个不行,少一个也不行

默认参数 也称关键字形参例如
def foo(x,y,z=1):
    print(x,y,z)
foo(2,y=3,z=4)
x 为位置形参 y=1为默认参数
2 为位置实参

1.5.2 默认参数

def test(x,y=2):
    print(x)
    print(y)
test(1)
test(1,3)
def conn(host,port=3306)
    pass
#默认参数特点:调用函数的时候,默认参数非必须传递
#用途: 1.默认安装
 

默认参数必须在位置参数的后面

def haha(x=1,y):
    print(x,y)
haha(2)
  File "C:/Users/Administrator/PycharmProjects/python18期/day3/函数.py", line 1
    def haha(x=1,y):
            ^
SyntaxError: non-default argument follows default argument

默认参数只在定义阶段赋值一次

x=100
def foo(a,b=x):
    print(a,b)
x=200000000000
foo('egon')

默认参数的值应该定义成不可变类型

1.5.3 命名关键字参数: 在*后面定义的形参成为命名关键字参数,必须是被以关键字实参的形式传值

def foo(name,age,*,sex,hobby):
    print(name,age,sex,hobby)
# foo('alex',73,'male','girl')
foo('alex',73,hobby='boy',sex='female')
foo(name='alex',sex='male',hobby='girl',age=74)

1.6 实参

1.6.1 位置实参:与形参按照位置一一对应

def test(x,y,z):
    print(x)
    print(y)
    print(z)
#位置调用

#1,2,3 为实参
#test(1,2,3)

1.6.2 关键字实参:按照key:value的形式指名道姓的给name传参的形式

def foo(name,age,sex,hobby):
    print(name,age,sex,hobby)
foo('alex',73,'male','girl')
foo(name='alex',sex='male',hobby='girl',age=74)

1.6.3 传参注意事项

位置实参必须在关键字实参的前面  
 
def foo(x,y,z=1):
    print(x,y,z)
foo(2,y=3,4)#这样调用会报错
不要对同一个形参传多次值
 

1.7 各种传参的结果

#*args:接受N个位置参数,转换成元组形式
# def test(*args):
#     print(args)
# test(1,2,3,4,5,5)
# test(*[1,2,3,4,5,5])# args = tuple
# def test1(x,*args):
#     print(x)
#     print(args)
# test1(1,2,3,4,5,6,7)
#**kwargs: 接受N个关键字参数,转换成字典的方式
# def test2(**kwargs):
#     print(kwargs)
#     print(kwargs['name'])
#     print(kwargs['age'])
#     # print(kwargs['sex'])
#     # print(kwargs['hobby'])
#
# test2(name='lieying',age=22,sex='man',hobby='gril')
# test2(**{'name':'alex','age':8})
#
# def test3(name,**kwargs):
#     print(name)
#     print(kwargs)
# test3('alex',age=18,sex='m')

# def test4(name,age=18,**kwargs):
#     print(name)
#     print(age)
#     print(kwargs)
#
# test4('alex',age=34,sex='m',hobby='tesla')
def logger(source):
    print("from %s" % source)
def test4(name,age=18,*args,**kwargs):
    print(name)
    print(age)
    print(args)
    print(kwargs)
    logger("TEST4")


test4('alex',age=34,sex='m',hobby='tesla')

1.8 高阶函数 意思是函数里套函数

def add(a,b,f):
    return f(a)+f(b)
res = add(3,-6,abs)
print(res)

1.8.1 高阶函数

def add(a,b,f):
    return f(a)+f(b)
res = add(3,-6,abs)
print(res)

D:python3.6python.exe C:/Users/Administrator/PycharmProjects/python18期/day2/高阶函数.py

9

1.8.2 递归

有明确的结束条件 python默认可以999层

问题规模每递归一次都应该比上一次的问题规模有所减少

效率低

def calc(n):
    print(n)
    if int(n/2)>0:
        return calc( int(n/2) )
    print('->',n)
calc(10)

1.9 函数式编程

是没有变量的

1.10 匿名函数

calc =lambda x:x*3

calc()

第2章 Day4

装饰器:

定义 本质是函数,(装饰其他函数)就是为其他函数添加附加功能

原则:

1,不能修改被装饰的函数的源代码

2,不能修改被装饰的函数的调用方式

门牌号都没有的时候(没有引用的时候) 内存存的值就会被释放回收  这就是垃圾回收

del x 删除的是变量名 不是变量值

函数先定义 再调用

没定义 调用就会报错

2.1 高阶函数

2.1.1 a:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

实例2-1   

import time
def bar():
    time.sleep(3)
    print('in the bar')
def test(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print('the func run time is %s' %(stop_time -  start_time))
test(bar)

2.1.2 b:返回值中包含函数名(不修改函数的调用方式)

import time

def bar():

    time.sleep(3)

    print('in the bar')

def test2(func):

    print(func)

    return func

# print(test2(bar))

bar=test2(bar)#把bar的内存地址传给bar

bar()  #run bar

2.2 嵌套函数

def foo():

    print('in the foo')

    def bar():

        print('in the bar')

    bar()

foo()

2.3 高阶函数+嵌套函数=》》装饰器

'''import time
def deco(func):
    start_time=time.time()
    func()
    stop_time=time.time()
    print(stop_time-start_time)
def test1():
    time.sleep(3)
    print('in the test1')
def test2():
    time.sleep(3)
    print('in the test2')
deco(test1)
deco(test2)
''' 
#利用高阶函数实现了功能但是 改变了原函数的调用方式


#接下来我们加一层嵌套函数 看能否不改变调用方式能否实现新加功能
import time
def timer(func):  #   timer(test1)  func=test1
   
def deco():
        start_time=time.time()
        func()  #  run test1()
       
stop_time=time.time()
        print('run time is %s'%(stop_time-start_time))
    return deco
@timer  # test1=timer(test1)
def test1():   
   
time.sleep(3)
    print('in the test1')
@timer # test2=timer(test2)
def test2():  
   
time.sleep(3)
    print('in the test2')
#print(timer(test1))
# test1=timer(test1)
# test2=timer(test2)
test1()
test2()
# deco(test1)
# deco(test2)

2.4 装饰器高潮版

2.5 列表生成式

>>>L = [x * 2 for x in range(10)]

>>> L

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

>>> g=(x * 2 for x in range(10))

>>> g

<generator object <genexpr> at 0x02CC5F80>

>>> for i in g:

   print(i)

  

0

2

4

6

8

10

12

14

16

18

>>> a= [ i for i in range(10)]

>>> a = map(lambda x:x+1, a)

>>> a

<map object at 0x02F66AD0>

>>> for i in a:print(i)

1

2

3

4

5

6

7

8

9

10

生成器只会在调用的时候才会生成相应的数据

只记录当前的位置只有一个__next__()方法。next()

[1,2,3,4,5,6,7,8,9]

2.6 斐波那契数列

def fib(max):
    n,a,b =0,0,1
    while n< max:
        yield b
        a,b =b,a+b
        n=n+1
    return '---done--' #异常的时候打印的消息
# fib(10)
# for n in fib(10):
#     print(n)
g=fib(10)
while True:
    try:
        x = next(g)
        print('g:',x)
    except StopIteration as e:
        print('Generator return value:',e)
        break
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
next 方法到没数据时会报错

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

2.7 迭代对象

可以直接用于for循环的对象统称为可迭代对象 Iterable

一类是集合数据类型,如list、tuple、dict、set、str等

一类是generator,包括生成器和带yield的generator function

可以使用isinstance()判断一个对象是否是Iterable对象:

>>> from collections import Iterable

>>> isinstance([],Iterable)

True

>>> isinstance({},Iterable)

True

>>> isinstance('abc',Iterable)

True

>>> isinstance((x for x in range(10)),Iterable)

True

>>> isinstance(100,Iterable)

False

2.8 迭代器

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator

>>> isinstance((x for x in range(10)), Iterator)

True

>>> isinstance([], Iterator)

False

>>> isinstance({}, Iterator)

False

>>> isinstance('abc', Iterator)

False

>>> 

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)

True

>>> isinstance(iter({}), Iterator)

True

>>> isinstance(iter('abc'), Iterator)

True

你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

or甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

for x in [1, 2, 3, 4, 5]:

    pass

# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
    try:
        # 获得下一个值:
        x = next(it)
    except StopIteration:
        # 遇到StopIteration就退出循环
        break
原文地址:https://www.cnblogs.com/lieying6011/p/7199433.html