程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

C#中的 Attribute 與 Python/TypeScript 中的裝飾器是同個東西嗎

編輯:Python

前言

最近成功把「前端帶師」帶入C#的坑(實際是前端帶師開始從cocos轉unity游戲開發了)

某天,「前端帶師」看到這段代碼後問了個問題:[這個是裝飾器]?

[HttpGet]
public Response Get() {
return ...
}

我第一反應覺得不是,這玩意在C#中叫“特性”(英文名Attribute,下文統稱為特性),在Java中叫注解,雖然寫法和Python/TypeScript中的差不多,但印象中實現方式應該是不同的。

但咱學理工科的就是要嚴謹,不能僅憑經驗和感覺,為此,我查了一下資料,看了之前楊旭大佬推薦的《C# in nutshell》這本書,不僅確認了這個問題的答案,也對Attribute有了更多了解。

關於AOP

“特性”、裝飾器,其實都是設計模式中的裝飾器模式,同時也是AOP思想。

AOP是Aspect Oriented Programming,即面向切面編程。

AOP把系統分解為不同的關注點,或者稱之為切面(Aspect),是一種在運行時,動態地將代碼切入到類的指定方法、指定位置上的編程思想

比如現在有一個網站,有購物、社交、游戲等多種功能且對所有用戶開放,現在需要限制只有高級會員才能使用其中的幾個功能,我們可以在每個模塊加上if判斷,但這樣侵入性太強,且會造成大量重復代碼;換成AOP的方法就是使用裝飾器,在需要高級會員的地方加上限制就行~

具體的區別

先來看看語法上的不同

Python的裝飾器

先來看看Python中的裝飾器,在Python中函數是一等公民,裝飾器也是個函數,其內部又內嵌了另一個函數

def outer(func):
def inner():
# ... 一些代碼
result = func()
return result
return inner

使用的時候

@outer
def test():
print('test')

使用時語法和Java的注解一樣,以@開頭

其實這是個語法糖,實際的效果等同於

outer(test)

test函數作為參數傳入給裝飾器,之後這段代碼的執行順序如下:

  • def outer(func):裝飾器定義
  • @outer:裝飾器語法糖,直接直接執行outer函數,將test函數作為參數傳入
  • outer:執行裝飾器語法規則,將test函數替換成inner函數
  • inner:執行inner函數代碼
  • test:根據inner中的這行代碼:result = func(),執行test函數代碼
  • 返回

在Python這種動態語言中,實現裝飾器模式確實是比靜態語言容易的,被裝飾的內容作為參數傳入裝飾器,裝飾器可以直接訪問到被裝飾的內容進行一些處理。

C#的“特性”

C#中,“特性”是一個類,繼承自Attribute類,然後可以包含任意你想要的屬性字段

AttributeUsage特性修飾,可以指定該特性可以修飾哪些代碼元素

[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DemoAttribute : Attribute {
public DemoAttribute(string param1) {
this.param1 = param1;
} public string param1 { get; set; }
}

構造方法中的參數,就是使用特性時傳入的參數,比如這樣:

[DemoAttribute("class")]
public class DemoClass {
[Demo("method")]
public void Method1() {
}
}

PS:特性使用時可以省略後面的"Attribute",所以DemoAttributeDemo是同個東西

這樣寫了之後並不會產生什麼效果

因為特性只是單純的裝飾

在代碼運行的時候,C#編譯器先實例化DemoAttribute這個類,然後再實例化DemoClass這個類,且在DemoAttribute內是無法獲取到被裝飾的內容的。

為了使裝飾起效果,需要搭配使用反射~

反射指程序可以訪問、檢測和修改它本身狀態或行為的一種能力。

通過下面的代碼可以獲取到裝飾在DemoClass上的特性

var info = typeof(DemoClass);
var attributes = info.GetCustomAttributes(true);

通過下面的代碼可以獲取被裝飾的方法,和裝飾參數啥的

foreach (var methodInfo in typeof(DemoClass).GetMethods()) {
var attribute = (DemoAttribute) Attribute.GetCustomAttribute(methodInfo, typeof(DemoAttribute));
if (attribute != null)
Console.WriteLine("方法 {0} 被裝飾,裝飾參數 {1}", methodInfo.Name, attribute.param1);
}

獲取到這些信息後,通過反射提供的其他功能再進行一些處理,也就實現了所謂的AOP

小結

所以,C#的特性和Python/TypeScript中的裝飾器,雖然寫法用法不一樣,但殊途同歸,要實現的目的確實是差不多的。

但要說是同樣的東西又不嚴謹,所以應該同樣的東西,不過都是各自語言中實現AOP的方式。

參考資料

  • C#的Attribute和Typescript的裝飾器之比較:https://blog.csdn.net/weixin_43263355/article/details/110137016
  • C#中如何實現類似Python中的裝飾器:https://www.zhihu.com/question/36211661
  • AOP面向切面編程:https://bbs.huaweicloud.com/blogs/289045

C#中的 Attribute 與 Python/TypeScript 中的裝飾器是同個東西嗎的更多相關文章

  1. guxh的python筆記三:裝飾器

    1,函數作用域 這種情況可以順利執行: total = 0 def run(): print(total) 這種情況會報錯: total = 0 def run(): print(total) tot ...

  2. python函數與方法裝飾器

    之前用python簡單寫了一下斐波那契數列的遞歸實現(如下),發現運行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...

  3. Python學習筆記012——裝飾器

    1 裝飾器 1.1裝飾器定義 在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator). 1.2 裝飾器分類 裝飾器:函數裝飾器,類裝飾器,函數的裝飾器,類的裝飾器 裝飾器:函數裝飾函 ...

  4. python設計模式之內置裝飾器使用(四)

    前言 python內部有許多內建裝飾器,它們都有特別的功能,下面對其歸納一下. 系列文章 python設計模式之單例模式(一) python設計模式之常用創建模式總結(二) python設計模式之裝飾 ...

  5. python 3.x 的裝飾器筆記

    今天學到了python的裝飾器,感覺這個東西還是稍微有些復雜,所以記錄下來,方便以後的查找.雖然標題是python 3.x的裝飾器,但是我也沒有怎麼用過python 2.x,感覺上應該是和python ...

  6. Python函數編程——閉包和裝飾器

    Python函數編程--閉包和裝飾器 一.閉包 關於閉包,即函數定義和函數表達式位於另一個函數的函數體內(嵌套函數).而且,這些內部函數可以訪問它們所在的外部函數中聲明的所有局部變量.參數.當其中一個 ...

  7. python基礎-內置裝飾器classmethod和staticmethod

    面向對象編程之classmethod和staticmethod classmethod 和 staticmethod都是python內置的裝飾器 classmethod 的作用:給在類內部定義的方法裝 ...

  8. python之閉包、裝飾器

    一.學習Python的時候發現函數內部,還可以寫函數,並且可以返回函數.覺得挺新奇的,主要是在探索裝飾器(有點像Java的注解)的時候,發現這個理解還是很主要的,所以這裡記錄一下. 二.閉包 1)首先 ...

  9. Python 入門之 Python三大器 之 裝飾器

    Python 入門之 Python三大器 之 裝飾器 1.開放封閉原則: (1)代碼擴展進行開放 ​ 任何一個程序,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改.所以我們必須允許代 ...

  10. Python模塊化編程與裝飾器

    Python的模塊化編程 我們首先以一個例子來介紹模塊化編程的應用場景,有這樣一個名為requirements.py的python3文件,其中兩個函數的作用是分別以不同的順序來打印一個字符串: # r ...

隨機推薦

  1. The Engine Document of JustWeEngine

    JustWeEngine - Android FrameWork An easy open source Android Native Game FrameWork. Github Game core ...

  2. python 反射的使用

    反射這個功能在很多編程語言中都有,在Python中自然也不例外.其實編程語言中的很多功能都能用簡單的代碼來驗證. 在code代碼之前,先簡單的了解下反射的幾個屬性. hasattr(obj,name_ ...

  3. 阿裡巴巴開源技術 WebX

    0. WebX項目目前已開源, 項目開源地址:https://github.com/webx/citrus-sample.git 項目參考文檔:http://www.openwebx.org/docs ...

  4. SharePoint基於windows驗證的如何通過組策略實現IE自動以當前域賬號登錄SP站點

    通過組策略實現IE自動以當前域賬號登錄SP站點 1. 在運行中運行MMC,啟動"組策略對象編輯器". 如下圖: 找到組策略如下圖: 找到域 點右鍵編輯 找到如下圖: 找到[計算機配 ...

  5. caffe中添加local層

    下載caffe-local,解壓縮; 修改makefile.config:我是將cuudn注釋掉,去掉cpu_only的注釋; make all make test(其中local_test出錯,將文 ...

  6. Nginx和PHP-FPM的啟動、重啟、停止腳本分享(轉)

    服務器上的Nginx和PHP都是源碼編譯安裝的,不像ubuntu一樣有自帶service啟動腳本,所以不支持類似以前的nginx (start|restart|stop|reload)了.自己動手豐衣 ...

  7. python 模擬ajax查詢社工庫...

    在windows中使用,輸入有關信息查詢社工庫,本來是網頁版的,我把ajax請求提取出來.粗略的封裝下,挺好玩. #coding:utf8 import urllib2,urllib from Bea ...

  8. python20151130

    tab和空格混排是報錯的 import os #如何獲取當前路徑 #當前路徑可以用'.'表示,再用os.path.abspath()將其轉換為絕對路徑 print(os.path.abspath('. ...

  9. CodeForce 569A

    Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u   Description Litt ...

  10. powerDesigner創建類及數據模型

    1.創建類圖 / 2.創建類圖的屬性 3.創建一個類,這個是創建後的對應關系,可以給其他的地方引用 3.創建類時候的屬性 name 和 code 取消關聯 4.創建兩個類的關系 這裡有個科普知識(ht ...


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved