代码改变世界

python之函数

2017-11-23 17:16  selfcourage  阅读(213)  评论(0)    收藏  举报
一、函数

 

 

1、函数分类:

#1、内置函数
为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()

#2、自定义函数
很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。

2、函数使用的原则:先定义,再调用

3、函数在定义阶段都干了哪些事?

#只检测语法,不执行代码 也就说,语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道

4、函数的参数(Point)

一 形参与实参

 

#-*- coding:utf-8 -*-
#函数的参数介绍
def foo(x,y):
    print(x,y)
#从实参数角度分析

#第一种 按照位置传值
foo(1,2)
foo(2,1)
#第二种 按照关键字传值
foo(x = 1,y = 2)
foo(y = 1,x = 2)
#第三种 混合传值
foo(1,y = 2)
#foo(y = 2,1) #关键字参数必须在位置参数的左边 对于一个参数只能赋值一次

#从形式参数角度分析
#第一种 按照位置传值 必须传值 多一个少一个都不行

#第二种 默认参数, #调用时可不传,
# def food(sex = 'name',y): #默认参数必须放在位置参数的后面
#     print(sex,y)
x = 1
def register(sex = x):
    # print(y)  #这里虽然报错了,但是只检测了语法 语法的没关系 调用的时候才会报错
    print(sex)

x = None
register() #打印结果是1 #在定义阶段就sex值就可以固定

#可变参数
#def func(x,*args) ->

#1、按照位置传值 多余的值会给args 并且保存为元祖的形式
def foo1(x,*args):
    print(x)    #1
    print(args) #(2, 33, 4322, 'f')  保存为元祖形式了!!
foo1(1,2,33,4322,'f')

#*args和默认参数混着用:
def foo2(x,y=1,*args):
    print(x)    #1
    print(y)    #y的值是2 传递给了y
    print(args) #(2, 33, 4322, 'f')  保存为元祖形式了!!
foo2(1,2,33,4322,'f')

def foo3(x,*args,y=1):  #*args 一般不和默认参数一起用  且*args放在位置参数的后面
    print(x)
    print(y)
    print(args)
foo3(1,2,33,4322,'f',y = 100)

#从实参的角度来看
def ab(x,y,z):
    print(x,y,z)
ab(*(1,2,3))  # *后面按照位置参数传值,args = (1,2,3)

#从形参角度来看
def foo(*args): #=>foo(1,2,3)
    print(args)
foo(1,2,3)

#**kwargs
def foo(x,**kwargs): #**kwargs是按照关键字传值之后 剩下的给kwargs作为字典
    print(x,kwargs)
foo(1,y=2,c=3) #关键字作为kwargs的字典形式

#从实参角度

def foo(x,y,z = 1):
    print(x,y,z)
foo(**{'a':1,'b':2}) #foo(a = 1,b = 2) 进行传值 ,报错

 

5、名称空间

内置名称空间 python提供的

全局名称空间  全局作用域 文件中存放的

import time => 导入模块是定义名字, 放到全局空间去  

局部名称空间 局部作用域

找变量:先局部-》全局-》内置

6 函数的嵌套调用

文件:1、当做脚本运行 2、当做模块被别人用 3、直接运行

二、 闭包

 

 

特点:#内部函数包含对外部作用域名字的引用而非全局作用域的引用

#-*- coding:utf-8 -*-
x = 1000
def f1():
    x = 1
    def f2():
        print(x)
    return f2
f = f1()
print(f()) #<function f1.<locals>.f2 at 0x00A4EA98> 说明f2是f1的内部函数,而且,还包含了对内部x1的引用 f2就是闭包函数
# print(f.__closure__[0].cell_content)
print(f.__closure__)

用途:

#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)
    from urllib.request import urlopen

    def index(url):
        def get():
            return urlopen(url).read()
        return get

    baidu=index('http://www.baidu.com')
    print(baidu().decode('utf-8'))
三、装饰器

 

 

装饰器就是闭包函数的一种应用场景

一 为何要用装饰器

#开放封闭原则:对修改封闭,对扩展开放

二 什么是装饰器

装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

三 装饰器的使用

无参装饰器

 

#-*- coding:utf-8 -*-

def timmer(func): #1
    def ff(*args,**kwargs):
        print(func)
        s_time = time.time()
        func(*args,**kwargs)
        e_time = time.time()
        print("77777777%s"%(e_time-s_time))
    return ff

import time #2
# def auth2(): #认证功能 #3 4
def auth(func): #<function index at 0x03B30ED0>
    def wrapper(*args,**kwargs):
        # if aa == "file":
        name = "fanglihua"
        password = "123"
        if name == "fanglihua" and password == "123":
            print("successful")
            ret = func(*args, **kwargs)
            return ret
        else:
            print("fail")
        # else:
        #     print("noen")
    return wrapper
    # return auth
#
# @timmer
# @auth2("file")
@auth
def index(name,password):
    print("Hello World")

# @auth
# def home(name):
#     print("flh")
#
# def my_max(  x,y):
#     ret = x if x> y else y
#     return ret

index("fanglihua","123")
# home("flh")
# x = my_max(2,3)
# print(x)

有参装饰器

#-*- coding:utf-8 -*-

import time
def auth2(aa):
    def auth(func):
        def wrapper(*args,**kwargs):
            if aa == "file":
                name = "fanglihua"
                password = "123"
                if name == "fanglihua" and password == "123":
                    print("successful")
                    ret = func(*args, **kwargs)
                    return ret
                else:
                    print("fail")
            else:
                print("noen")
        return wrapper
    return auth

@auth2("file")
def index(name,password):
    print("Hello World")

@auth2
def home(name):
    print("flh")

def my_max(x,y):
    ret = x if x> y else y
    return ret

index("fanglihua","123")
# home("flh")
# x = my_max(2,3)
# print(x)

四 装饰器语法

被装饰函数的正上方,单独一行
        @deco1
        @deco2
        @deco3
        def foo():
            pass

        foo=deco1(deco2(deco3(foo)))

五 装饰器补充:wraps

from functools import wraps

def deco(func):
    @wraps(func) #加在最内层函数正上方
    def wrapper(*args,**kwargs):
        return func(*args,**kwargs)
    return wrapper

@deco
def index():
    '''哈哈哈哈'''
    print('from index')

print(index.__doc__)

六 练习题