網站首頁 編程語言 正文
相信大家都用過?jupyter,也用過里面的魔法命令,這些魔法命令都以?%?或者?%%?開頭,我們舉個例子。
用法還是比較簡單的,但是我們能不能自定義魔法命令呢?毫無疑問是可以的,因為上面的?%%cython?就是 Cython 模塊自定義的。
所以命令可以是 jupyter 內置的,比如?%time,直接拿來就能用;還可以是第三方模塊里面的,在 jupyter 通過?%load_ext?加載之后,再嵌入進來。下面就來看看如何自定義魔法命令。
from?IPython.core.magic?import?(
????magics_class,
????Magics,
????line_magic,
????cell_magic
)
@magics_class
class?MagicOrder(Magics):
????"""
????自定義一個類,類名叫什么無所謂
????但要繼承?Magics,并且要被?magics_class?裝飾
????"""
????@line_magic
????def?hello(self,?line):
????????"""
????????在 jupyter 中就可以使用如下命令,比如:
????????%hello?<Your?Code>,然后就會調用這個?hello?方法
????????參數?line?就是?%hello?后面的代碼
????????"""
????????print(f"line:?{line}")
????@cell_magic
????def?world(self,?line,?cell):
????????"""
????????在 jupyter 中就可以使用如下命令,比如:
????????%%world
????????<Your?Code>
????????<Your?Code>
????????...
????????然后就會調用這個?world?方法
????????參數?cell?就是?%%world?下面整個單元格的代碼
????????然后還有一個參數?line,它表示?%%world?所在行后面的代碼
????????但對于?%%?開頭的命令來說,我們一般都會新起一行,然后寫代碼
????????所以?line?這個參數暫時用不到
????????"""
????????print(f"line:?\n{line}")
????????print("-----------------")
????????print(f"cell:?\n{cell}")
#?必須定義?load_ipython_extension?函數
#?%load_ext?本質上也是加載一個模塊
#?但它會自動調用該函數
def?load_ipython_extension(ip):
????#?在函數內部,我們將類?MagicOrder?注冊進去
????#?然后就可以使用它內部的魔法命令了
????ip.register_magics(MagicOrder)
#?如果不定義此函數,那么使用?%load_ext?加載時會報錯
#?The?xxx?module?is?not?an?IPython?extension.
當前模塊叫 main.py,我們來測試一下:
結果沒有問題,但說實話對于 %% 開頭的命令來說,我們很少會在它后面寫代碼,基本都是新起一行,就像下面這個樣子。
自定義命令我們已經實現了,并且也知道怎么獲取輸入的代碼了,下面要做的就是執行它。而將字符串當成代碼執行,我們可以使用內置函數 exec。
@magics_class
class?MagicOrder(Magics):
????@line_magic
????def?hello(self,?line):
????????exec(line)
????@cell_magic
????def?world(self,?line,?cell):
????????exec(cell)
代碼的其它部分不變,然后你覺得接下來調用魔法命令會執行成功嗎?我們測試一下:
神奇的地方出現了,雖然命令執行成功了,但執行完之后,告訴我們變量未定義。其實原因很好想,我們調用 exec 的時候沒有指定名字空間,那么默認會影響 exec 函數所在的名字空間,即 hello 和 world 函數的名字空間。
當打開一個 jupyter 的時候,內部相當于啟動了一個 shell,所以在調用 exec 的時候,應該將整個 shell 的名字空間傳進去。
from?IPython.core.magic?import?(
????magics_class,
????Magics,
????line_magic,
????cell_magic,
????needs_local_scope
)
@magics_class
class?MagicOrder(Magics):
????@line_magic
????def?hello(self,?line):
????????#?通過?self.shell.user_ns
????????#?可以拿到當前?shell?的名字空間
????????#?注意:包含所有的單元格
????????local_ns?=?self.shell.user_ns
????????#?在?local_ns?當中執行代碼
????????exec(line,?local_ns,?local_ns)
????@needs_local_scope
????@cell_magic
????def?world(self,?line,?cell,?local_ns):
????????#?或者通過?needs_local_scope?裝飾器
????????#?這樣在調用函數的時候,會額外傳遞一個?local_ns?參數
????????#?該參數和?self.shell.user_ns?等價
????????exec(cell,?local_ns,?local_ns)
def?load_ipython_extension(ip):
????ip.register_magics(MagicOrder)
然后再來測試一下:
此時就沒有任何問題了。
下面我們模仿 jupyter 的 %time 命令,實現一個?%my_time,來加深一遍印象。
@magics_class
class?MagicOrder(Magics):
????@needs_local_scope
????@line_magic
????def?my_time(self,?line,?local_ns):
????????start?=?time.perf_counter()
????????exec(line,?local_ns,?local_ns)
????????end?=?time.perf_counter()
????????print(f"總耗時:?{round(end?-?start,?3)}")
測試一下:
結果沒有問題,是我們想要的結果。
最后再來看看如何設置可選參數,舉一個 Cython 的例子:
我們說對于以 %%?開頭的命令,應該新起一行,在它的下面寫代碼。而之所以新起一行,是因為命令所在的行,要用于設置可選參數。那么問題來了,如何設置指定的可選參數呢?
from?IPython.core.magic?import?(
????magics_class,
????Magics,
????cell_magic,
????needs_local_scope
)
from?IPython.core?import?magic_arguments
@magics_class
class?MagicOrder(Magics):
????@magic_arguments.magic_arguments()
????#?在?jupyter?中可以通過?-n=xxx?或者?--name=xxx
????#?然后是?dest="name",用于指定參數的名字
????#?后續便可以通過?name?字段來獲取該參數的值
????@magic_arguments.argument(
????????"-n",?"--name",?dest="name",?default="satori"
????)
????#?"-"?和?"--"?可以只出現一個,并且默認解析得到的是字符串
????#?而?age?我們希望是整數,所以指定?type?為?int
????#?解析完參數之后,會自動調用?int?進行轉化
????#?如果不指定該參數,則使用?default
????#?而這里沒有?default,那么結果就是?None
????@magic_arguments.argument(
????????"--age",?dest="age",?type=int
????)
????@magic_arguments.argument(
????????"-h",?"--hobby",?dest="hobby",?default=[],
????????action="append"
????)
????@needs_local_scope
????@cell_magic
????def?order(self,?line,?cell,?local_ns):
????????#?顯然?line?就是可選參數,cell?就是代碼塊
????????exec(cell,?local_ns,?local_ns)
????????#?解析參數
????????args?=?magic_arguments.parse_argstring(
????????????self.order,?line)
????????#?打印
????????print(args)
def?load_ipython_extension(ip):
????ip.register_magics(MagicOrder)
我們測試一下:
還是很簡單的,而且這里的參數解析和 argparse 模塊非常類似,可以自己看一下。
原文鏈接:https://mp.weixin.qq.com/s/yiBWcoZitavGWBA0osedow
相關推薦
- 2022-09-26 python中創建一個包并引用使用的操作方法_python
- 2022-04-10 Blazor頁面組件用法介紹_基礎應用
- 2022-07-25 Android自定義View原理(實戰)_Android
- 2023-10-13 el-table中點擊跳轉到詳情頁的兩種方法
- 2022-10-04 python中xml格式的轉換方法_python
- 2024-03-03 ElementUi tab組件切換導致echarts寬度變窄問題
- 2022-04-14 Mac快速解決zsh: command not found: conda的方法
- 2022-07-30 Linux計劃任務介紹
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支