首页 > 其他分享 >函数

函数

时间:2022-10-11 21:47:35浏览次数:37  
标签:index 函数 spam global time print def

global与nonlocal

一、global

总之一句话,作用域是全局的,就是会修改这个变量对应地址的值。
global语句是一个声明,它适用于整个当前代码块。这意味着列出的标识符将被解释为全局变量。尽管自由变量可以能指的是全局变量而不被声明为全局变量。
global语句中列出的名称不得用于该全局语句之前的文本代码块中。
global语句中列出的名称不能定义为形式参数,也不能在for循环控制目标、class定义、函数定义、impot语句或变量注释中定义。
1、global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。
gcount = 0
def global_test():
  gcount+=1
  print (gcount)
global_test()

以上代码会报错:第一行定义了全局变量,在内部函数中又对外部函数进行了引用并修改,那么python会认为它是一个局部变量,有因为内部函数没有对其gcount进行定义和赋值,所以报错。

2、如果局部要对全局变量修改,则在局部声明该全局变量
gcount = 0
def global_test():
  global gcount
  gcount+=1
  print (gcount)
global_test()

以上输出为:1

3、如果局部不声明全局变量,并且不修改全局变量,则可以正常使用
gcount = 0
def global_test():
  print (gcount)
global_test()

二、nonlocal

只在闭包里面生效,作用域就是闭包里面的,外函数和内函数都影响,但是闭包外面不影响。
nonlocal语句使列出的标识符引用除global变量外最近的封闭范围中的以前绑定的变量。这很重要,因为绑定的默认行为是首先搜索本地名称空间。该语句允许封装的代码将变量重新绑定到除全局(模块)作用域之外的本地作用域之外。

nonlocal 语句中列出的名称与 global 语句中列出的名称不同,它们必须引用封闭范围中已经存在的绑定(无法明确确定应在其中创建新绑定的范围)。

1、 nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量

def make_counter():
  count = 0
  def counter():
    nonlocal count
    count += 1
    return count
  return counter   
def make_counter_test():
 mc = make_counter()
 print(mc())
 print(mc())
 print(mc())
make_counter_test()

以上输出为:

​ 1

​ 2

​ 3

三、混合使用

def scope_test():
  def do_local():
    spam = "local spam" #此函数定义了另外的一个spam字符串变量,并且生命周期只在此函数内。此处的spam和外层的spam是两个变量,如果写出spam = spam + “local spam” 会报错
  def do_nonlocal():
    nonlocal spam    #使用外层的spam变量
    spam = "nonlocal spam"
  def do_global():
    global spam
    spam = "global spam"
  spam = "test spam"
  do_local()
  print("After local assignmane:", spam)
  do_nonlocal()
  print("After nonlocal assignment:",spam)
  do_global()
  print("After global assignment:",spam)
  
scope_test()
print("In global scope:",spam)

以上输出为:

After local assignmane: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam

函数名的多种用法

1.函数可以当作值被赋予变量

def func():
    bu = (1,2,3,'abc',{'name':'ligen'})
    print (bu)

a = func
a()

2.函数名可以当作函数的参数

def func(*args):
    dict1 = {'name':args[0],'age':args[1],'box':args[2]}
    for key in dict1:
        print (key)
    print ('*'*20)
    for value in dict1.values():
        print (value)
    print ('*' * 20)
    for kv in dict1.items():
        print (kv)

# func('ligen', 24, 'blue')
def func2(f):
    f
func2(func('ligen', 24, 'blue'))

3.函数可以当作元素放在容器中

def func1():
    print ('1')

def func2():
    list1 = [func1,func1,func1]
    for i in list1:
        i()
func2()

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

def func():
    def foo():
        print(222)
    return foo
a = func()
a()

闭包函数

定义在函数内部的函数 并且用到了外部函数名称空间中的名字

1.定义在函数内容
2.用到外部函数名称空间中的名字
给函数传参的方式有俩种,分别为用形参和闭包

1. 形参
		def index(a):
		    print('from index', a)

2. 闭包
		def outer(name):
    		def inner():
        		print(name)
   		 	return inner  

		x = outer('XWenXiang')  # x = outer() = inner
		x()  # x() = inner()

(1) 代码执行后首先在第一行定义函数 outer() 并定义形参 name 
(2) 第二步调用函数 outer() 并传入实参 XWenXiang 
(3) 第三步执行函数 outer() 函数体代码,定义函数 inner() ,返回值 inner,inner也就是函数 
inner的内存地址
(4) 第四步将函数 outer() 返回值赋值给 x 。
(5) 第五步调用函数 x() 因为此时 x 等价与 inner 的内存地址。

装饰器

1.什么是装饰器

器指的是工具,可以定义成函数

装饰指的是为其他事物添加额外的东西点缀

合到一起的解释:
    装饰器指的定义一个函数,该函数是用来为其他函数添加额外的功能
    就是拓展原来函数功能的一种函数

2.为何要用装饰器

开放封闭原则

开放:指的是对拓展功能是开放的

封闭:指的是对修改源代码是封闭的

装饰器就是在不修改被装饰器对象源代码以及调用方式的前提下为被装饰对象添加新功能

3.如何用

# 需求:在不修改index函数的源代码以及调用方式的前提下为其添加统计运行时间的功能
def index(x, y):
    time.sleep(3)
    print('index %s %s' % (x, y))


index(111, 222)
# index(y=111,x=222)
# index(111,y=222)
# 解决方案一:失败
# 问题:没有修改被装饰对象的调用方式,但是修改了其源代码
import time


def index(x, y):
    start = time.time()
    time.sleep(3)
    print('index %s %s' % (x, y))
    stop = time.time()
    print(stop - start)


index(111, 222)
# 解决方案二:失败
# 问题:没有修改被装饰对象的调用方式,也没有修改了其源代码,并且加上了新功能
#      但是代码冗余
import time


def index(x, y):
    time.sleep(3)
    print('index %s %s' % (x, y))


start = time.time()
index(111, 222)
stop = time.time()
print(stop - start)
# 解决方案三:失败
# # 问题:解决了方案二代码冗余问题,但带来一个新问题即函数的调用方式改变了
import time


def index(x, y):
    time.sleep(3)
    print('index %s %s' % (x, y))


def wrapper():
    start = time.time()
    index(111, 222)
    stop = time.time()
    print(stop - start)


wrapper()
# 方案三的优化一:将index的参数写活了
import time


def index(x, y, z):
    time.sleep(3)
    print('index %s %s %s' % (x, y, z))


def wrapper(*args, **kwargs):
    start = time.time()
    index(*args, **kwargs)  # index(3333,z=5555,y=44444)
    stop = time.time()
    print(stop - start)


wrapper(3333, 4444, 5555)
wrapper(3333, z=5555, y=44444)
# 方案三的优化二:在优化一的基础上把被装饰对象写活了,原来只能装饰index
import time

def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)


def outter(func):
    # func = index的内存地址
    def wrapper(*args,**kwargs):
        start=time.time()
        func(*args,**kwargs) # index的内存地址()
        stop=time.time()
        print(stop - start)
    return wrapper

index=outter(index) # index=wrapper的内存地址
home=outter(home) # home=wrapper的内存地址


home('egon')
# home(name='egon')
# 方案三的优化三:将wrapper做的跟被装饰对象一模一样,以假乱真
import time

def index(x,y,z):
    time.sleep(3)
    print('index %s %s %s' %(x,y,z))

def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)

def outter(func):
    def wrapper(*args,**kwargs):
        start=time.time()
        res=func(*args,**kwargs)
        stop=time.time()
        print(stop - start)
        return res



    return wrapper
# # 偷梁换柱:home这个名字指向的wrapper函数的内存地址
home=outter(home)


res=home('egon') # res=wrapper('egon')
print('返回值--》',res)

装饰器模板

def outer(func):
    def inner(*args, **kwargs):
        res = func(*args, **kwargs)
        return res
    return inner

装饰器语法糖

在用装饰器之前还要写上 index = calculate_time(index) 这样一行代码,显然是很不方便的。这时候可以用 @calculate_time 替换 index = calculate_time(index)

import time   #导入时间模块
 
def calculate_time(f):
    def inner():
         start_time = time.time()
         f()
         end_time = time.time()
         print(end_time - start_time)
    return inner
 
@calculate_time      # 等价于index = calculate_time(index) 这行赋值的代码
def index():
    time.sleep(2.2)    #时间休眠2.2秒
 
index()         #2.2051877975463867

点击查看图片来源

标签:index,函数,spam,global,time,print,def
From: https://www.cnblogs.com/oiqwyig/p/16782666.html

相关文章

  • 闭包函数与装饰器
    昨日内容回顾函数的参数位置参数 分为位置形参和位置实参,位置形参与实参数量要一致,使用关键字传参可改变赋值顺序。默认参数 函数定义阶段赋有默认值的参数,传参时可不......
  • 函数之装饰器
    global与nonlocal1.局部名称空间直接修改全局名称空间中的数据money=123defindex():globalmoneymoney=222index()print(money)2.内层局部名称空间修......
  • 函数(三)——闭包函数与装饰器
    一、函数名的多种用法函数名其实绑定的是一块内存地址,只不过该地址里面存放的不是数据值而是一段代码,函数名加括号就会找到该代码并执行。1. 可以当做变量名赋值defi......
  • 函数剩余内容/函数装饰器
    目录今日内容概要1.global与nonlocal用法2.函数名的多种用法3.闭包函数4.装饰器介绍5.装饰器原理推导过程6.装饰器模板7.装饰器语法糖练习题及答案今日内容概要global和......
  • 闭包函数与装饰器
    今日内容总结global与nonlocalmoney=666defindex():globalmoneymoney=123index()print(money)"""局部名称空间直接修改全局空间中的数据"""......
  • 函数装饰器
    目录内容概要内容详解global与nonlocal函数名的多种用法闭包函数装饰器简历装饰器推导流程装饰器模板装饰器语法糖内容概要global与nonlocal函数名的多种用法闭包......
  • 函数与装饰器
    目录global与nonlocal函数名的多种用法函数闭包装饰器简介装饰器推导流程装饰器模板装饰器语法糖作业global与nonlocal1global关键字:在函数中,如果想给全局变量赋值,则需......
  • 函数对象与闭包函数与装饰器
    目录一.global与nonlocal二.函数名的多种用法1.可以当做变量名赋值2.可以当做函数的参数3.可以当做函数的返回值4.可以当做容器类型的数据三.闭包函数四.装饰器1.装饰器简......
  • python基础之闭包函数与装饰器
    python基础之闭包函数与装饰器目录一、global与nonlocal二、函数名的多种用法1.可以当变量名2.可以当函数的参数3.可以当函数的返回值三、闭包函数1.闭包函数的实际应用四......
  • C语言-函数
    1:函数的概念函数是一个命名了的代码块,我们通过调用函数执行相应的代码,函数可以有0个或者多个参数,而且会产生一个结果对于我的总结:我觉得函数可以说是一个能够实现一定功......