python 閉包&裝飾器(一)

来源:https://www.cnblogs.com/ss-long/archive/2019/02/15/10385753.html
-Advertisement-
Play Games

一、閉包 1.舉例 註意:inner()是局部變數,在全局範圍不可調用(即不能直接調用inner()函數),但是在法二中,在執行完 f = outer() 之後,outer()函數就已經結束,執行f()的時候卻可以調用inner()函數,並輸出x的值,這是因為outer()里 return 的 in ...


一、閉包

1.舉例

def outer():
    x = 10

    def inner():   # 內部函數
        print(x)    # 外部函數的一個變數

    return inner

# 調用inner()函數的方法
outer()()   # 法一

f = outer()
f()         # 法二

     註意:inner()是局部變數,在全局範圍不可調用(即不能直接調用inner()函數),但是在法二中,在執行完 f = outer() 之後,outer()函數就已經結束,執行f()的時候卻可以調用inner()函數,並輸出x的值,這是因為outer()里 return 的 inner是一個閉包函數,裡面有x這個環境變數

2.閉包的定義:(閉包 = 內部函數 + 定義環境時的變數)

       如果在一個內部函數里,對在外部作用域(非全局)的變數(外部環境變數可以有很多)進行引用,那麼內部函數就被稱為閉包(如上例)。閉包函數為外部環境變數  在內部函數里引用提供了途徑

二、裝飾器

1.裝飾器的定義及舉例:

舉例:

假如我們現在寫一個函數f():

def f():
    print('你是天才嗎')

但是後來客戶要求在調用f()函數的同時,要顯示執行f()函數花費的多長時間,然後我們寫瞭如下的顯示函數:

import time

def show_time():
    start = time.time()   # 顯示電腦此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
    f()
    time.sleep(1)    # 執行完f()之後停留一秒再執行下麵的語句,因為f()的執行時間太短顯示不出
    end = time.time()
    print("spend %s" % (end - start))


def f():
    print('你是天才嗎')


show_time()

我們通過執行show_time() 執行了f()函數,並且返回了執行f()函數所花費的時間,但是卻改變了調用方式,以前是直接調用f(),現在是調用show_time() ,這樣做對於應用 此函數的人員影響很大,因為他們要把所有用f()函數的都改過來,而且如果要計算其他函數的執行時間,就要修改show_time()函數內部或者另外寫一個函數,代碼的重覆率高,所以我們再做一個改進:

import time

def show_time(func):

    def inner():      #定義一個外部函數
        start = time.time()   # 顯示電腦此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
         func()
        time.sleep(1)    # 執行完f()之後停留一秒再執行下麵的語句,因為f()的執行時間太短顯示不出
         end = time.time()
        print("spend %s" % (end - start))
    return inner

def f():
    print('你是天才嗎')

f = show_time(f)  # 此後我們不管需要那個函數的執行時間,只需要把 f 修改為對應的函數名即可
f()

對於 f = show_time(f)  還有一種寫法:

import time

def show_time(func):

    def inner():      #定義一個外部函數        
start = time.time()   # 顯示電腦此刻的時間(不是傳統的時間,而是linux自誕生至今所經過的時間)
         func()
        time.sleep(1)    # 執行完f()之後停留一秒再執行下麵的語句,因為f()的執行時間太短顯示不出
         end = time.time()
        print("spend %s" % (end - start))
    return inner

@show_time   #  相當於 f = show_time(f) 
def f():
    print('你是天才嗎')
 
f()

定義:函數show_time() 就是一個裝飾器,它把真正的方法func包在了函數裡面,看起來像func()被上下的時間函數裝飾了,  @符號是裝飾器的語法,在定義函數的時候使用,避免再一次賦值

image

當程式運行時先執行@show_time,@show_time 幫我們做的就是當執行f() 時,執行的代碼從黃框轉向紅框部分,相當於給了inner()一個執行的參數,僅此而已


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [TOC] 1.目標 爬取每個頁面鏈接的內部內容和投訴信息 2.方法1:通過Spider爬取 python coding: utf 8 import scrapy from dongguanSpider.items import DongguanItem class SunSpider(scrapy ...
  • 向後臺提交數據除了前端url,form表單,Ajax外還可以用cookie,secure_cookie,提交更多信息可以在用cookie基礎上用session, cookie,secure_cookie提交用戶數據:瀏覽器訪問1頁面,後端判斷前端瀏覽器提供的用戶對不對,對的話,設置cookie或se ...
  • 在ActiveMQ、RabbitMQ、RocketMQ、Kafka消息中間件之間,我們為什麼要選擇Kafka? ...
  • 前言 由於業務需要,需要在攔截器中操作Redis緩存,按照 controller,service層配置發現無法註入,一直報空指針異常。 解決方案 攔截器: 查詢原因 攔截器執行在Bean初始化之前導致這個問題的。在web.xml中各個元素的執行順序是這樣的,context param listene ...
  • 輸入:只能輸入A-Z(不區分大小寫),0-9和下劃線; 第一行輸入應輸入字元串,第二行輸入實際輸入字元串。 輸出:按大寫輸出缺少的字元,每個字元輸出一次。 註意: 1、由於不區分大小寫,則需要將小寫字母識別為大寫字母; 2、保證每個字元只出現一次。 思路: 1、將所有的字母都轉化為大寫字母; 2、挨 ...
  • 前言 前段時間,博客和論壇都放到的阿裡雲新購的三年 T5 實例伺服器上,等都轉移過去才發現,所謂的 T5 實例只能滿足10% 的 CPU 峰值。期間經歷了各種卡頓、死機,最終又把博客單獨遷移了回來。靜態文件走 CDN,文章都 Redis,以為萬事大吉了就。 群壓 然並卵,有一天,群里有網友說要壓測我 ...
  • 啟動了兩個goroutine,並完成一些工作。在各自迴圈的每次迭代之後,在goroutine 會使用LoadInt64 來檢查shutdown 變數的值。這個函數會安全地返回shutdown 變數的一個副本。如果這個副本的值為1,goroutine 就會跳出迴圈並終止。 ...
  • 父進程退出時,子進程會如何?如何確保父進程退出時,子進程也退出? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...