自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

用 Jupyter Notebook 教 Python

開發(fā) 后端
有了 Jupyter、PyHamcrest,用一點測試的代碼把它們連在一起,你就可以教任何適用于單元測試的 Python 內(nèi)容。

[[343595]]

有了 Jupyter、PyHamcrest,用一點測試的代碼把它們連在一起,你就可以教任何適用于單元測試的 Python 內(nèi)容。

關于 Ruby 社區(qū)的一些事情一直讓我印象深刻,其中兩個例子是對測試的承諾和對易于上手的強調(diào)。這兩方面最好的例子是 Ruby Koans,在這里你可以通過修復測試來學習 Ruby。

要是我們能把這些神奇的工具也用于 Python,我們應該可以做得更好。是的,使用 Jupyter Notebook、PyHamcrest,再加上一點類似于膠帶的粘合代碼,我們可以做出一個包括教學、可工作的代碼和需要修復的代碼的教程。

首先,需要一些“膠布”。通常,你會使用一些漂亮的命令行測試器來做測試,比如 pytest 或 virtue。通常,你甚至不會直接運行它。你使用像 tox 或 nox 這樣的工具來運行它。然而,對于 Jupyter 來說,你需要寫一小段粘合代碼,可以直接在其中運行測試。

幸運的是,這個代碼又短又簡單:

  1. import unittest
  2.  
  3. def run_test(klass):
  4.     suite = unittest.TestLoader().loadTestsFromTestCase(klass)
  5.     unittest.TextTestRunner(verbosity=2).run(suite)
  6.     return klass

現(xiàn)在,裝備已經(jīng)就緒,可以進行第一次練習了。

在教學中,從一個簡單的練習開始,建立信心總是一個好主意。

那么,讓我們來修復一個非常簡單的測試:

  1. @run_test
  2. class TestNumbers(unittest.TestCase):
  3. def test_equality(self):
  4. expected_value = 3 # 只改這一行
  5. self.assertEqual(1+1, expected_value)
  1. test_equality (__main__.TestNumbers) ... FAIL
  2. ======================================================================
  3. FAIL: test_equality (__main__.TestNumbers)
  4. ----------------------------------------------------------------------
  5. Traceback (most recent call last):
  6. File "<ipython-input-7-5ebe25bc00f3>", line 6, in test_equality
  7. self.assertEqual(1+1, expected_value)
  8. AssertionError: 2 != 3
  9. ----------------------------------------------------------------------
  10. Ran 1 test in 0.002s
  11. FAILED (failures=1)

“只改這一行” 對學生來說是一個有用的標記。它準確地表明了需要修改的內(nèi)容。否則,學生可以通過將第一行改為 return 來修復測試。

在這種情況下,修復很容易:

  1. @run_test
  2. class TestNumbers(unittest.TestCase):
  3. def test_equality(self):
  4. expected_value = 2 # 修復后的代碼行
  5. self.assertEqual(1+1, expected_value)
  1. test_equality (__main__.TestNumbers) ... ok
  2. ----------------------------------------------------------------------
  3. Ran 1 test in 0.002s
  4. OK

然而,很快,unittest 庫的原生斷言將被證明是不夠的。在 pytest 中,通過重寫 assert 中的字節(jié)碼來解決這個問題,使其具有神奇的屬性和各種啟發(fā)式方法。但這在 Jupyter notebook 中就不容易實現(xiàn)了。是時候挖出一個好的斷言庫了:PyHamcrest。

  1. from hamcrest import *
  2. @run_test
  3. class TestList(unittest.TestCase):
  4. def test_equality(self):
  5. things = [1,
  6. 5, # 只改這一行
  7. 3]
  8. assert_that(things, has_items(1, 2, 3))
  1. test_equality (__main__.TestList) ... FAIL
  2. ======================================================================
  3. FAIL: test_equality (__main__.TestList)
  4. ----------------------------------------------------------------------
  5. Traceback (most recent call last):
  6. File "<ipython-input-11-96c91225ee7d>", line 8, in test_equality
  7. assert_that(things, has_items(1, 2, 3))
  8. AssertionError:
  9. Expected: (a sequence containing <1> and a sequence containing <2> and a sequence containing <3>)
  10. but: a sequence containing <2> was <[1, 5, 3]>
  11. ----------------------------------------------------------------------
  12. Ran 1 test in 0.004s
  13. FAILED (failures=1)

PyHamcrest 不僅擅長靈活的斷言,它還擅長清晰的錯誤信息。正因為如此,問題就顯而易見了。[1, 5, 3] 不包含 2,而且看起來很丑:

  1. @run_test
  2. class TestList(unittest.TestCase):
  3. def test_equality(self):
  4. things = [1,
  5. 2, # 改完的行
  6. 3]
  7. assert_that(things, has_items(1, 2, 3))
  1. test_equality (__main__.TestList) ... ok
  2. ----------------------------------------------------------------------
  3. Ran 1 test in 0.001s
  4. OK

使用 Jupyter、PyHamcrest 和一點測試的粘合代碼,你可以教授任何適用于單元測試的 Python 主題。

例如,下面可以幫助展示 Python 從字符串中去掉空白的不同方法之間的差異。

  1. source_string = " hello world "
  2.  
  3. @run_test
  4. class TestList(unittest.TestCase):
  5. # 這是個贈品:它可以工作!
  6. def test_complete_strip(self):
  7. result = source_string.strip()
  8. assert_that(result,
  9. all_of(starts_with("hello"), ends_with("world")))
  10.  
  11. def test_start_strip(self):
  12. result = source_string # 只改這一行
  13. assert_that(result,
  14. all_of(starts_with("hello"), ends_with("world ")))
  15.  
  16. def test_end_strip(self):
  17. result = source_string # 只改這一行
  18. assert_that(result,
  19. all_of(starts_with(" hello"), ends_with("world")))
  1. test_complete_strip (__main__.TestList) ... ok
  2. test_end_strip (__main__.TestList) ... FAIL
  3. test_start_strip (__main__.TestList) ... FAIL
  4. ======================================================================
  5. FAIL: test_end_strip (__main__.TestList)
  6. ----------------------------------------------------------------------
  7. Traceback (most recent call last):
  8. File "<ipython-input-16-3db7465bd5bf>", line 19, in test_end_strip
  9. assert_that(result,
  10. AssertionError:
  11. Expected: (a string starting with ' hello' and a string ending with 'world')
  12. but: a string ending with 'world' was ' hello world '
  13. ======================================================================
  14. FAIL: test_start_strip (__main__.TestList)
  15. ----------------------------------------------------------------------
  16. Traceback (most recent call last):
  17. File "<ipython-input-16-3db7465bd5bf>", line 14, in test_start_strip
  18. assert_that(result,
  19. AssertionError:
  20. Expected: (a string starting with 'hello' and a string ending with 'world ')
  21. but: a string starting with 'hello' was ' hello world '
  22. ----------------------------------------------------------------------
  23. Ran 3 tests in 0.006s
  24. FAILED (failures=2)

理想情況下,學生們會意識到 .lstrip() 和 .rstrip() 這兩個方法可以滿足他們的需要。但如果他們不這樣做,而是試圖到處使用 .strip() 的話:

  1. source_string = " hello world "
  2.  
  3. @run_test
  4. class TestList(unittest.TestCase):
  5. # 這是個贈品:它可以工作!
  6. def test_complete_strip(self):
  7. result = source_string.strip()
  8. assert_that(result,
  9. all_of(starts_with("hello"), ends_with("world")))
  10.  
  11. def test_start_strip(self):
  12. result = source_string.strip() # 改完的行
  13. assert_that(result,
  14. all_of(starts_with("hello"), ends_with("world ")))
  15.  
  16. def test_end_strip(self):
  17. result = source_string.strip() # 改完的行
  18. assert_that(result,
  19. all_of(starts_with(" hello"), ends_with("world")))
  1. test_complete_strip (__main__.TestList) ... ok
  2. test_end_strip (__main__.TestList) ... FAIL
  3. test_start_strip (__main__.TestList) ... FAIL
  4. ======================================================================
  5. FAIL: test_end_strip (__main__.TestList)
  6. ----------------------------------------------------------------------
  7. Traceback (most recent call last):
  8. File "<ipython-input-17-6f9cfa1a997f>", line 19, in test_end_strip
  9. assert_that(result,
  10. AssertionError:
  11. Expected: (a string starting with ' hello' and a string ending with 'world')
  12. but: a string starting with ' hello' was 'hello world'
  13. ======================================================================
  14. FAIL: test_start_strip (__main__.TestList)
  15. ----------------------------------------------------------------------
  16. Traceback (most recent call last):
  17. File "<ipython-input-17-6f9cfa1a997f>", line 14, in test_start_strip
  18. assert_that(result,
  19. AssertionError:
  20. Expected: (a string starting with 'hello' and a string ending with 'world ')
  21. but: a string ending with 'world ' was 'hello world'
  22. ----------------------------------------------------------------------
  23. Ran 3 tests in 0.007s
  24. FAILED (failures=2)

他們會得到一個不同的錯誤信息,顯示去除了過多的空白:

  1. source_string = " hello world "
  2.  
  3. @run_test
  4. class TestList(unittest.TestCase):
  5. # 這是個贈品:它可以工作!
  6. def test_complete_strip(self):
  7. result = source_string.strip()
  8. assert_that(result,
  9. all_of(starts_with("hello"), ends_with("world")))
  10.  
  11. def test_start_strip(self):
  12. result = source_string.lstrip() # Fixed this line
  13. assert_that(result,
  14. all_of(starts_with("hello"), ends_with("world ")))
  15.  
  16. def test_end_strip(self):
  17. result = source_string.rstrip() # Fixed this line
  18. assert_that(result,
  19. all_of(starts_with(" hello"), ends_with("world")))
  1. test_complete_strip (__main__.TestList) ... ok
  2. test_end_strip (__main__.TestList) ... ok
  3. test_start_strip (__main__.TestList) ... ok
  4. ----------------------------------------------------------------------
  5. Ran 3 tests in 0.005s
  6. OK
在一個比較真實的教程中,會有更多的例子和更多的解釋。這種使用 Jupyter Notebook 的技巧,有的例子可以用,有的例子需要修正,可以用于實時教學,可以用于視頻課,甚至,可以用更多的其它零散用途,讓學生自己完成一個教程。

 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2022-11-14 11:52:34

DataspellJupyterLabNotebook

2022-05-05 12:25:46

Jupyter開發(fā)

2023-07-28 09:59:31

2020-12-18 08:00:00

Python開發(fā)Web

2021-03-26 12:07:14

JupyterPython編程語言

2023-11-05 12:31:07

Jupyter命令

2019-07-28 20:38:33

2020-07-26 11:55:11

Jupyter Not擴展工具開發(fā)

2024-01-03 16:37:26

Jupyter工具開源

2022-07-28 08:33:59

JupyterPython

2022-06-20 10:00:57

Python工具包代碼

2019-07-23 11:20:16

2021-08-12 16:02:22

Jupyter NotPython命令

2023-05-24 16:48:47

Jupyter工具技巧

2021-05-26 10:15:52

開發(fā)技能工具

2020-11-04 10:31:29

Jupyter NotPython數(shù)據(jù)分析

2023-07-29 22:15:33

2020-08-04 06:51:28

Jupyterpython開發(fā)

2019-11-08 09:46:34

技術功能開發(fā)

2019-09-22 18:53:27

Jupyter Not代碼開發(fā)
點贊
收藏

51CTO技術棧公眾號