third day -- 02--函数

复习

 

 1 # 函数
 2     # 定义
 3         # 关键字 def 函数名(形参):
 4         # 参数 :
 5             # 位置参数
 6             # *args  动态传参 :接收在调用的时候传过来的多余的所有按位置传的参数
 7             # 关键字参数 默认参数,如果不传会有一个默认的值,如果传了会覆盖默认的值
 8             # **kwargs  动态传参 :接收在调用的时候传过来的多余的所有按关键字传的参数
 9         # 返回值
10             # return 停止一个程序的运行,返回参数
11                 # 没有返回值 默认返回None
12                 # 有一个返回值
13                 # 返回多个值
14     # 调用
15         # 调用的关键字 函数名(实参)
16         # 传参数 :
17             # 按照位置传
18             # 按照关键字传
19         # 接收返回值
20             # 没有返回值 不接受
21             # 有一个返回值 用一个变量接收
22             # 有多个返回值
23                 # 用一个变量接收 所用返回值都会被组织成一个元组
24                 # 用多个变量接收 有多少个返回值 就必须用多少个变量接收
25 # 函数是第一类对象的概念
26     # 函数名 --> 函数的内存地址
27     # 函数名可以作为 容器类型的元素 函数的参数、返回值 还能进行赋值  --> 变量
28 
29 # 闭包和装饰器
30     # 闭包的定义 : 内部函数引用外部函数的变量
31     # 闭包的应用 :装饰器
View Code

 

 

 

 

1,函数的初识。
函数的定义,函数体,函数名。

函数的返回值return。

函数的参数。
实参:
三种

形参:
三种。
动态参数。


#一、函数概念
1.未引入函数时:代码重复;可读性差
 1 # li = [1, 2, 3, 43, 'fdsa', 'alex']
 2 # count = 0
 3 # for i in li:
 4 #     count += 1
 5 # print(count)
 6 #
 7 # s1 = 'fdsgdfkjlgdfgrewioj'
 8 #
 9 # count = 0
10 # for i in s1:
11 #     count += 1
12 # print(count)
View Code

2.def 函数名 (): #函数名定义与变量相同
函数体
3.函数名+() 执行函数
4.print(len(s1)) 未调用函数,打印长度
5.函数中一般不加print
6.函数的返回值:
return
1.遇到return,函数结束 与break相似
def func1():
        print(11)
        return
        print(22)
    func1()
return结束函数

2.给函数的调用者(执行者)提供返回值 #函数调用者:函数名()整体
1.无return返回None
s1='lijie123456'
def my_len():
    count=0
    for i in s1:
        count+=1
print(my_len())  #None
View Code

2.return不写或者None 返回None
3.return返回单个数
s1='lijie123456'

# def my_len():
#     count=0
#     for i in s1:
#         count+=1
#     return 666
# print(my_len(),type(my_len()))   #666 <class 'int'>
返回单个数

4.return返回多个数将放在元祖中返回
s1='lijie123456'
# def my_len():
#     count=0
#     for i in s1:
#         count+=1
#     return 666,count,'丽姐'
# print(my_len(),type(my_len()))  #(666, 11, '丽姐') <class 'tuple'>
多个数

5:return分别赋值功能!!!
s1='lijie123456'
# def my_len():
#     count=0
#     for i in s1:
#         count+=1
#     return 666,222,count
# ret1,ret2,ret3=my_len() (666,222,11)
# print(ret1) #666
# print(ret2) #222
# print(ret3)  #11
分别赋值

基本实现了等同于len的功能,但s1改变,for循环中in后就要改变,引入参数的概念
s1='123'
# def my_len():
#     count = 0
#     for i in s1:
#         count += 1
#     return count
# print(my_len())
# print(len(s1))
不含参数

3.函数的传参:函数的定义,形参;函数的执行,实参
#函数的传参
li = [1, 2, 3, 43, 'fdsa', 'alex']
s1 = 'fdsgdfkjlgdfgrewioj'

# def my_len(a):  # 函数的定义()放的是形式参数,形参
#     count = 0
#     for i in a:
#         count += 1
#     return count
# ret = my_len(li)  # 函数的执行() 实际参数,实参
# print(ret)
# print(len(s1))
函数的传参

二、参数传值方法

我们告诉mylen函数要计算的字符串是谁,这个过程就叫做 传递参数,简称传参,我们调用函数时传递的这个“hello world”和定义函数时的s1就是参数。

实参与形参

参数还有分别:

我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。

定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。 

传递多个参数

参数可以传递多个,多个参数之间用逗号分割。
实参形参理解
'''
从实参角度:
1.位置参数 必须一一对应,按顺序
def f(x,y):
    print(x,y)
f(1,2)
View Code

2.关键字参数 必须一一对应,不分顺序
def f(x,y,z):
    print(x,y,z)
f(y=1,x=2,z=3)
关键字参数

#输出最大值

def max_number(x,y):  #注意传值
    if x>y:
        return x
    else:
        return y
print(max_number(110,1))

#三元运算符

def max(a,b):
    ret=a if a>b else b
    #print(ret)
print(max(1,2))  #为什么结果为None??max中无返回值

正确写法:
def max(a,b):
    return a if a>b else b
print(max(1,2))
View Code

3.混合参数:一一对应且关键字参数在位置参数后
# def func2(argv1,argv2,argv3):
#     print(argv1)
#     print(argv2)
#     print(argv3)
# func2(1,2,argv3=4)
View Code


从形参角度
1.位置参数 同实参,必须一一对应,按顺序
# def func1(x,y):
#     print(x,y)
# func1(1,2)
View Code

2.默认参数 必须在位置参数后面
 1 # def regedit(name,sex):
 2 #     with open('regedit',encoding='utf-8',mode='a') as f1:
 3 #         f1.write('{} {}\n'.format(name,sex))
 4 #
 5 # while True:
 6 #     name=input('请输入名字:/q 或Q退出')
 7 #     if name.upper()=='Q':break
 8 #     sex=input('请输入性别;')
 9 #     regedit(name,sex)
10 # #默写加默认参数
11 def regedit(name,sex='male'):
12     with open('regedit',encoding='utf-8',mode='a')as f1:
13         f1.write('{} {} \n'.format(name,sex)) #注意) 的位置
14 while True:
15     name=input('请输入名字:/q或Q退出')
16     if name.upper()=='Q':break
17     if 'a' in name:
18         sex=input('请输入性别:')
19         regedit(name,sex)
20     else:
21         regedit(name)
默认参数

3.动态参数 *args,**kwargs 万能参数
*args元祖(所有位置参数) **kwargs字典(所有关键字参数)
def func2(*args,**kwargs):
    print(args)
    print(kwargs)
func2(1,2,3,4,5,6,7,11,'alex','老男孩',a='ww',b='qq',c='222')

#(1, 2, 3, 4, 5, 6, 7, 11, 'alex', '老男孩')
#{'a': 'ww', 'b': 'qq', 'c': '222'}
View Code

三种类型顺序:位置参数---*args----默认参数---**kwargs
def func3(a,b,*args,sex='',**kwargs):
    print(a)
    print(b)
    print(sex)
    print(args)
    print(kwargs)
func3(1,2,'老男孩','alex','wusir',sex='n',name='alex',age=46)
# 1
# 2
# n
# ('老男孩', 'alex', 'wusir')
# {'name': 'alex', 'age': 46}
func3(1,2,'老男孩','alex','wusir',name='alex',age=46)
# 1
# 2
# 男
# ('老男孩', 'alex', 'wusir')
# {'name': 'alex', 'age': 46}
顺序

一定要记住!!
函数的执行 在实参中加* 打散
函数的定义 加* 聚合
不加**,字典可以放在元祖里
def func1(*args,**kwargs):  # 函数的定义 * 聚合。
    print(args)
    print(kwargs)
# l1 = [1,2,3,4]
# l11 = (1,2,3,4)
# l2 = ['alex','wusir',4]
# func1(*l1,*l2,*l11)  # 函数的执行:* 打散功能。
# # func1(1,2,3,4,'alex','wusir',4,1,2,3,4)  # 函数的执行:* 打散功能。
dic1 = {'name1':'alex'}
dic2 = {'name2':'laonanhai'}
func1(dic1,dic2)    #({'name1': 'alex'}, {'name2': 'laonanhai'})  /{}

func1(*dic1,**dic2) 
#('name1',)
#{'name2': 'laonanhai'}

func1(**dic1,**dic2)  
#()
#{'name1': 'alex', 'name2': 'laonanhai'}
View Code

2,函数的进阶。
名称空间,全局名称空间,局部名称空间,内置名称空间,
作用域。
globals locals
global,nonlocal
作用域链。
函数的名字。
闭包。

'''
函数的进阶
1.名称空间:
全局名称空间
局部名称空间
内置名称空间
2.作用域
全局作用域:全局名称空间和内置名称空间
局部作用域:作用于局部名称空间
3.加载顺序:内置名称空间--全局名称空间--局部作用空间(函数执行时)
取值顺序:局部名称空间---全局名称空间---内置名称空间
# name = 'alex'
# age = 12
# def func1():
#     name1 = 'wusir'
#     age1 = 34
# func1()
# print(name1)  #会报错,name1没有被定义
#临时名称空间:临时名称空间,局部名称空间,存入函数里面的变量与值的关系,随着函数的执行结束,临时名称空间消失。

#名称空间:全局名称空间,局部名称空间,内置名称空间。
#作用域:
    # 全局作用域:全局名称空间,内置名称空间。
    # 局部作用域:局部名称空间

#加载顺序,取值顺序。
#加载顺序:内置名称空间 ----> 全局名称空间----> 局部名称空间(函数执行时)
#取值顺序:局部名称空间 ---> 全局名称空间 ----> 内置名称空间
# name1 = 'wusir'
# def func1():
#     print(name1)
#     def func2():
#         print('****',name1)
#     func2()
# func1()

# name1 = 'wusir'
# def func1():
#     name2 = 'laonanhai'
#     print(globals()) #所有的方法{'__name__': '__main__', '__doc__': "\n文件\n操作文件\n1.文件路径\n2.编码方式\n3,动作mode\n\n代码\n# f1 = open('D:\\空姐护士老师主妇.txt', encoding='utf-8', mode='r')\n# content = f1.read()\n# print(content)\n# f1.close()\n解释\n 1,打开文件,产生文件句柄。\n 2,操作文件句柄。\n3.关闭文件!!\n\n", '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001DCA208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/Users/venv/third day/0415课上笔记.py', '__cached__': None, 's1': 'lijie123456', 'name1': 'wusir', 'func1': <function func1 at 0x0000000001D22EA0>}
#     print(locals()) #查看本地的方法{'name2': 'laonanhai'}
# func1()
View Code

4.关键字 global nonlocal
局部名称变量可以引用全局变量,但不能做改变,会报错;要用到关键字
1 name = 'alex'
2 age = 12
3 def func1():
4     global name1
5     name1= 'wusir'
6     age1 = 34
7 func1()
8 print(name1)
View Code


global
1.声明全局变量
2.更改全局变量
fun1() 执行函数!
#关键字:global nonlocal
# count = 1
# def func1():
#     count = count + 1
#     print(count) #未执行,执行会报错
#global 1,声明一个全局变量
       #2,更改一个全局变量
# name = 'wusir'
# def func1():
#     global name
#     name = 'alex'
#     return  #在此处写不写都可以
# func1()
# print(name)  #alex
View Code

nonlocal 用处少,改变局部变量
  1,不能修改全局变量。
  2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
def func1():
    name1 = 'alex'
    print('+',name1)
    def inner():
        nonlocal name1
        name1= 'wusir'
        print('*',name1)
        def inner1():
            pass
    inner()
    print('%',name1)
func1()

结果:
+ alex
* wusir
% wusir
nonlocal

5.函数名
1.可以互相赋值
# def func1():
#     print(666)
#
# f1 = func1
# f1()
View Code

2.函数名可以当成函数的参数
def func1():
    print(666)
def func2(argv):
    argv()
    print(777)
func2(func1)
View Code

3.可以当成容器类 数据类型的参数
# def func1():
#     print(666)
#
# def func2():
#     print(777)
#
# def func3():
#     print(888)
#
# l1 = [func1, func2, func3]
# for i in l1:
#     i()
View Code

4.函数名可以当成函数的返回值

777 666!!!
加()就执行
def func1():
    print(666)
def func2(argv): 
    print(777)
    return argv  #func1()

ret = func2(func1)
ret() #执行func2(func1)
View Code

方法,查看全局变量、局部变量,返回在字典中
globals()
locals()



#执行inner函数
# def wrapper():
#     def inner():
#         name1 = 'alex'
#         print(name1)
#     inner()
# wrapper()

# #练习理解
def wrapper():
    def inner():
        name1 = 'alex'
        print(name1)
    return inner   #相当于inner()
ret=wrapper()
ret()
执行inner的两种方法
ret=wrapper() #inner

6.闭包:内层函数对外层函数非全局变量的引用
1.判断是不是闭包
函数名.__closure__ #None 不是 cell是

一般会有面试题
闭包的好处:如果python检测到闭包,它有一个机制,
局部作用域不会随着程序的结束而结束
# 闭包 内层函数对外层函数非全局变量的引用,叫做闭包
#闭包的好处:如果python 检测到闭包,
# 他有一个机制,你的局部作用域不会随着函数的结束而结束。

# def wrapper():
#     name1 = '老男孩'
#     def inner():
#         print(name1)
#     inner()
#     print(inner.__closure__)  # cell
# wrapper()
# 判断是不是闭包
# name1 = '老男孩'
# def wrapper():
#     def inner():
#         print(name1)
#     inner()
#     print(inner.__closure__)  # None
# wrapper()

# name = 'alex'
# def wrapper(argv):
#     def inner():
#         print(argv)
#     inner()
#     print(inner.__closure__)  # cell
# wrapper(name)
View Code

index()() #第一个()返回return get,再加一个()执行get
一般用于爬虫、装饰器
有回收机制
from urllib.request import urlopen
# def index():
#     url = "http://www.cnblogs.com/jin-xin/articles/8259929.html"
#     def get():
#         return urlopen(url).read()
#     return get
# name1 = 'alex'
# content1 = index()()  #第一个()返回return get,再加一个()执行get
# content2 = index()()
# print(content1)
爬虫小例子

'''

 

3,装饰器。

'''
装饰器
1.梳理调用inner例子--最简单版的装饰器
2.语法糖 @

在不改变原函数即原函数的调用的情况下,为原函数登录增加一些特殊功能,打印日志、执行时间、登录认证
 1 import time
 2 def func1():
 3     print('晚上回去吃烧烤....')
 4     time.sleep(0.5)
 5 
 6 def timer(f1):  # f1 = func1
 7     def inner():
 8         start_time = time.time()
 9         f1()
10         end_time = time.time()
11         print('此函数的执行效率%s' %(end_time-start_time))
12     return inner
13 #方法1
14 # f1=func1
15 # func1=timer
16 # func1(f1)()  #timmer(func1)
17 #方法2
18 # func1=timer(func1) #inner
19 # func1()  #inner()
20 #方法3
21 @timer
22 def func1():
23     print('晚上回去吃烧烤....')
24     time.sleep(0.5)
25 func1()
View Code

3.带参数的装饰器
两个* **
 1 import time
 2 # def wrapper():
 3 #     def inner():
 4 #         name1 = 'alex'
 5 #         print(name1)
 6 #     inner()
 7 # wrapper()
 8 
 9 # def wrapper():
10 #     def inner():
11 #         name1 = 'alex'
12 #         print(name1)
13 #     return inner
14 # ret = wrapper()  # inner
15 # ret()
16 def func1():
17     print('晚上回去吃烧烤....')
18     time.sleep(0.3)
19 
20 def func2():
21     print('晚上回去喝啤酒....')
22     time.sleep(0.3)
23 
24 # 最简单版的装饰器
25 # def timer(f1):  # f1 = func1
26 #     def inner():
27 #         start_time = time.time()
28 #         f1()
29 #         end_time = time.time()
30 #         print('此函数的执行效率%s' %(end_time-start_time))
31 #     return inner
32 '''
33 # f = func1
34 # func1 = timer
35 #
36 # func1(f)  # timmer(func1)
37 '''
38 # func1 = timer(func1)  # inner
39 # func1()  # inner()
40 
41 
42 # @
43 def timer(f1):  # f1 = func1
44     def inner():
45         start_time = time.time()
46         f1()
47         end_time = time.time()
48         print('此函数的执行效率%s' %(end_time-start_time))
49     return inner
50 
51 @timer  # func1 = timer(func1)
52 def func1():
53     print('晚上回去吃烧烤....')
54     time.sleep(0.3)
55 @timer # func2 = timer(func2)
56 def func2():
57     print('晚上回去喝啤酒....')
58     time.sleep(0.3)
59 func1()  # inner()
60 func2()  # inner()
View Code
 1 #装饰器:在不改变原函数即原函数的调用的情况下,
 2 # 为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等。
 3 
 4 #被装饰函数带参数
 5 # def timer(f1):  # f1 = func1
 6 #     def inner(*args,**kwargs):
 7 #         start_time = time.time()
 8 #         f1(*args,**kwargs)  # func1()
 9 #         end_time = time.time()
10 #         print('此函数的执行效率%s' %(end_time-start_time))
11 #     return inner
12 #
13 # @timer  # func1 = timer(func1)  inner
14 # def func1(a,b):
15 #     print(a,b)
16 #     print('晚上回去吃烧烤....')
17 #     time.sleep(0.3)
18 # func1(111,222)  # inner(111,222)
19 
20 #被装饰函数带参数
21 # def timer(f1):  # f1 = func1
22 #     def inner(*args,**kwargs):
23 #         start_time = time.time()
24 #         ret = f1(*args,**kwargs)  # func1()
25 #         end_time = time.time()
26 #         print('此函数的执行效率%s' %(end_time-start_time))
27 #         return ret
28 #     return inner
29 #
30 # @timer  # func1 = timer(func1)  inner
31 # def func1(a,b):
32 #     print(a,b)
33 #     print('晚上回去吃烧烤....')
34 #     time.sleep(0.3)
35 #     return 666
36 # ret2 = func1(111,222)  # inner(111,222)
37 # print(ret2)
带参数
结构:
def wrapper(f1):
    def inner(*args,**kwargs):
        '''执行函数之前的操作'''
        ret = f1(*args,**kwargs)
        '''执行函数之后的操作'''
        return ret
    return f1

# @wrapper
# def func1():
#     print(222)
#     return 333
# print(func1())

  



'''

 


4,装饰器的进阶。

 

posted @ 2018-04-16 22:51  yuyou123  阅读(159)  评论(0编辑  收藏  举报