Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
How to Write Robust Python Code
Search
HayaoSuzuki
May 29, 2023
Technology
4.8k
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
How to Write Robust Python Code
BPStudy#189
https://bpstudy.connpass.com/event/283616/
HayaoSuzuki
May 29, 2023
More Decks by HayaoSuzuki
See All by HayaoSuzuki
Let's implement useless Python objects (revised)
hayaosuzuki
0
63
Tomorrow graphlib, Let us use everybody
hayaosuzuki
1
2.4k
Tasting "Python Distilled"
hayaosuzuki
0
420
Let's implement useless Python objects
hayaosuzuki
0
2.1k
Unknown Evolution of the Built-in Function pow
hayaosuzuki
0
1.5k
Python for Everyday
hayaosuzuki
1
2.5k
How to Use In-Memory Streams
hayaosuzuki
1
6.5k
Do you know cmath module?
hayaosuzuki
0
3.4k
Elementary Number Theory with Python
hayaosuzuki
1
3.7k
Other Decks in Technology
See All in Technology
自主式軟體工廠
philipz
0
250
カンファレンスに参加した後の浮遊感とセルフケア
pauli
0
320
実践! SRE × AI - ABEMA における AIOps -
tetsuya28
7
2.7k
AIは爆速なのに、私が詰まっていた話 ― 音声入力と鳴くマスコットでボトルネックを削る
yama3133
0
590
DWH の限界突破! AI エージェント向け爆速リアルタイムデータ基盤 ClickHouse
jozono
1
360
Getting Started with Google Antigravity
glaforge
0
140
ai_cording_with_k8s_knowledge.pdf
mochizuki875
1
330
脆弱性診断って、何をしているの? 〜弱点を見つけて、会社の改善につなげるまで〜
keeg
0
820
TinyGoでオブザーバビリティ?OpenTelemetryはTinyGoで使えるのか / Is OpenTelemetry available in TinyGo environment?
ymotongpoo
2
130
転んだ話が背中を預ける理由になる / A_story_about_falling_down_gives_you_a_reason_to_watch_each_other_s_backs.pdf
pauli
3
350
Claude Code本は、どのように執筆チームで書かれたか
oikon48
1
360
味覇で作るパスタが美味い - 20261001_yabaubuki.dev
livesense
PRO
0
120
Featured
See All Featured
The Cult of Friendly URLs
andyhume
79
7k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
Ethics towards AI in product and experience design
skipperchong
2
420
[SF Ruby Conf 2025] Rails X
palkan
3
1.4k
Between Models and Reality
mayunak
4
490
RailsConf 2023
tenderlove
30
1.6k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Crafting Experiences
bethany
1
380
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
42k
SEO for Brand Visibility & Recognition
aleyda
0
4.8k
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
How to Ace a Technical Interview
jacobian
280
24k
Transcript
ݎ࿚ͳ Python ίʔυΛॻ͘ํ๏ ʰϩόετ PythonʱΛಡ͏ Hayao Suzuki BPStudy#189 May 29,
2023
Who am I ? ͓લ୭Α ໊લ Hayao Suzukiʢླɹॣʣ Twitter @CardinalXaro
ࣄ Software Developer @ BeProud Inc. › גࣜձࣾϏʔϓϥυ › IT ษڧձࢧԉαʔϏε connpass › ΦϯϥΠϯֶशαʔϏε PyQ › γεςϜ։ൃͷͨΊͷυΩϡϝϯταʔϏε Tracery › 2023 5 ݄ 23 ʹཱ 17 पΛܴ͑ͨ 2 / 46
Who am I ? ༁ٕͨ͠ज़ॻ › ϩόετ Python(O’Reilly Japan) New!
› ೖ Python 3 ୈ 2 ൛ (O’Reilly Japan) ࠪಡٕͨ͠ज़ॻʢൈਮʣ › Effective Python ୈ 2 ൛ (O’Reilly Japan) › ϚΠΫϩϑϩϯτΤϯυ (O’Reilly Japan) › ϚΠΫϩαʔϏεΞʔΩςΫνϟ ୈ 2 ൛ (O’Reilly Japan) › SQL Ͱ͡ΊΔσʔλੳ (O’Reilly Japan) New! https://xaro.hatenablog.jp/ ʹϦετ͕͋Γ·͢ɻ 3 / 46
Who am I ? ൃදϦετʢൈਮʣ › ϨΨγʔ Django ΞϓϦέʔγϣϯͷݱԽ (DjangoCongress
JP 2018) › SymPy ʹΑΔࣜॲཧ (PyCon JP 2018) › Python ͱָ͠Ήॳ (PyCon mini Hiroshima 2019) › ܅ cmath Λ͍ͬͯΔ͔ (PyCon mini Shizuoka 2020) › ΠϯϝϞϦʔετϦʔϜ׆༻ज़ (PyCon JP 2020) › ΈࠐΈؔ pow ͷΒΕ͟ΔਐԽ (PyCon JP 2021) https://xaro.hatenablog.jp/ ʹϦετ͕͋Γ·͢ɻ 4 / 46
ࠓͷςʔϚ ݪஶʰRobust Pythonʱ ஶऀ Patrick Viafore ग़൛ࣾ O’Reilly Media ൃߦ
2021 7 ݄ ༁ʰϩόετ Pythonʱ ༁ऀ ླ ॣ ༁ɺඌ ߴ߂ ༁ ग़൛ࣾ O’Reilly Japan ൃߦ 2023 3 ݄ ඌ͞ΜɺླͷϖΞʰೖ Python 3 ୈ 2 ൛ʱҎདྷ 2 ճ 5 / 46
ࠓͷςʔϚ ʰϩόετ PythonʱΛಡ͏ › ͬ͟ͱɺͲΜͳࣄ͕ॻ͍ͯ͋Δͷ͔հ͠·͢ › 384 ϖʔδͷ༰Λ 30 ͰಡΜͩؾʹͳΖ͏ʂ
6 / 46
ϩόετ Python ͷߏ 4 ෦ߏ ୈ I ෦ ܕΞϊςʔγϣϯ ୈ
II ෦ Ϣʔβఆٛܕ ୈ III ෦ େنͳมߋͷରԠ ୈ IV ෦ ηʔϑςΟωοτͷߏங ͳ͓ɺୈ 1 ষʮϩόετ Python ೖʯಋೖͱͳΔষ 7 / 46
ैདྷͷٕज़ॻͱͷҧ͍ Python ͱܕώϯτ › ܕώϯτ Python 3.5 ͰಋೖʢPEP 484ʣ ›
Python 3.5 2015 9 ݄ʹϦϦʔε ܕώϯτͷ͚ํ͢ͰʹͬͯΔΑ › ܕώϯτͷ͚ํͷղઆهࣄॻ੶ଟ͍ʢ8 ͷੵʣ › ܕώϯτͷӡ༻ํ๏ߟ͑ํʹ౿ΈࠐΜͩຊଘࡏ͢Δͷ͔ ͦͦɺதڃऀҎ্͚ͷ Python ຊͷઈର͕গͳ͍ΑͶ 8 / 46
ϩόετ Python ͷ͕͍͜͜͢͝ ϩόετ Python ͷಛ › ܕώϯτʹ͍ͭͯ 14 ষʹΘͨͬͯৄࡉʹղઆʢୈ
I ෦ɺୈ II ෦ʣ › ϩόετͳઃܭʢୈ III ෦ʣ › ܕώϯτܕ͚ͩͰΧόʔ͖͠Εͳ͍ཁૉରԠʢୈ IV ෦ʣ 9 / 46
ϩόετ Python ͷओ ʰϩόετ Pythonʱ͕ݴ͍͍ͨ͜ͱ › σʔλܕͱίϛϡχέʔγϣϯखஈͰ͋Δ › ͕ࣗίʔυͰදݱ͍ͨ͜͠ͱΛσʔλܕΛͬͯ໌֬ʹ͑Α͏ 10
/ 46
ୈ 1 ষ ϩόετ Python ೖ ϩόετ Python ͬͯͲΜͳຊ ཁ͢Δʹɺຊॻϩόετʢؤৎ/ؤ݈/ݎ࿚ʣͳ
Python Λॻͨ͘ΊͷຊͰ͋Δɻ ʢP. 1ʣ ͦͦϩόετͬͯԿʁ ίʔυϕʔεͷϩόετωεͱɺઈ͑ͣมԽͯ͠ٱੑ͕ߴ͘ɺΤϥʔΛى͜͞ͳ ͍͜ͱͰ͋Δɻ ʢP. 4ʣ 11 / 46
ୈ 1 ষ ϩόετ Python ೖ ͳͥϩόετʹ͢Δඞཁ͕͋Δͷ͔ʁ ͦͷ͑ͷ֩৺ίϛϡχέʔγϣϯʹ͋Δɻ ʢதུʣͦͷͨΊʹɺকདྷͷϝϯςφ ͱձΘͳͯࣗ͘ͷڌͱҙਤ͕ΘΔΑ͏ʹ͍ͨ͠ɻ
12 / 46
ୈ 1 ষ ϩόετ Python ೖ ྫɿ ԿΛ͢ΔؔͰ͠ΐ͏͔ʁ def adjust_recipe(recipe,
servings): old_servings = recipe.pop(0) factor = servings / old_servings # ؆୯ʹܭଌͰ͖Δ͚ͩΛ͍ͬͯͩ͘͞ new_recipe = {ingredient: (amount * factor, unit) for ingredient, amount, unit in recipe} new_recipe["servings"] = servings return new_recipe 13 / 46
ୈ 1 ষ ϩόετ Python ೖ ίϛϡχέʔγϣϯͷྨ ۙੑ ใͷൃ৴ऀͱड৴ऀͷؒʹ͋Δ࣌ؒతͳڑ ίετ
ίϛϡχέʔγϣϯʹඞཁͳ࿑ྗ 14 / 46
ୈ 1 ষ ϩόετ Python ೖ ͳͥϩόετʹ͢Δඞཁ͕͋Δͷ͔ʁ ͦͷ͑ͷ֩৺ίϛϡχέʔγϣϯʹ͋Δɻ ʢதུʣͦͷͨΊʹɺকདྷͷϝϯςφ ͱձΘͳͯࣗ͘ͷڌͱҙਤ͕ΘΔΑ͏ʹ͍ͨ͠ɻ
ͦͷͨΊʹʁ ະདྷͷϝϯςφʹҙਤΛ͑ΔʹɺίετͰۙੑ͕ෆཁͳίϛϡχέʔγϣϯ͕ ඞཁͰ͋Δɻ 15 / 46
ୈ 1 ষ ϩόετ Python ೖ ίετͰۙੑ͕ෆཁͳίϛϡχέʔγϣϯ › ίʔυΛಡΉ͚ͩͰཧղͰ͖ΕΑ͍ ›
ίʔυΛཧղ͢Δͷʹඞཁͳ࣌ؒΛ࠷খݶʹ͍͑ͨ ͦͷͨΊʹʁ σʔλܕͷબকདྷͷ։ൃऀʹରͯࣗ͠ͷҙਤΛදݱ͢Δ͜ͱͰ͋Γɺਖ਼͍͠σʔ λܕΛબ͢Εอकੑ্͕͢Δɻ ʢP. 19ʣ 16 / 46
ୈ 1 ষ ϩόετ Python ೖ ྫɿ ԿΛ͢ΔؔͰ͠ΐ͏͔ʁ from fractions
import Fraction def adjust_recipe(recipe: Recipe, servings: int) -> Recipe: # ࡐྉσʔλͷίϐʔΛ࡞Δ new_ingredients = list(recipe.get_ingredients()) recipe.clear_ingredients() for ingredient in new_ingredients: ingredient.adjust_proportion( Fraction(servings, recipe.servings) ) return Recipe(servings, new_ingredients) 17 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 2 ষ Python σʔλܕೖ › Python
ڧ͍ܕ͚ݴޠ › Python ಈతܕ͚ݴޠ ಈతܕ͚ݴޠຊ࣭తʹϩόετͰͳ͍ͷ͔ › ಈతܕ͚ݴޠͰϩόετʹॻ͚Δɺগ͠େมͳ͚ͩ › ੩తܕ͚ݴޠͷ߹ΑΓΑ͘ߟ͑Δඞཁ͕͋Δ › ੩తܕ͚ݴޠΛ͑ඞͣ͠ϩόετʹॻ͚ΔΘ͚Ͱͳ͍ 18 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 3 ষ ܕΞϊςʔγϣϯ › ܕώϯτͷߏจతͳ͚ํ͍ͬͯΔΑͶʢ8 ͷੵʣ
› ܕώϯτπʔϧʢmypy ͳͲʣͱΈ߹ΘͤͯਅՁΛൃش͢Δ ܕώϯτ mypy λμͰͳ͍ › ެ։ APIɺϥΠϒϥϦͷΤϯυϙΠϯτ › ෳࡶͳܕɺΘ͔Γʹ͍͘ܕ › mypy ઌੜͷࢦࣔʹै͏ 19 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 4 ষ ܕ੍ › Optional Ͱ͵ΔΆόάΛ௵ͦ͏
› Union ͰදݱՄೳͳঢ়گΛݮͦ͏ › Literal Ͱ͞Βʹ੍Λ͔͚Α͏ › Final ͰఆͰ͋Δͱओு͠Α͏ › NewType ͰજࡏతͳόάΛ௵ͦ͏ Annotated ͷ͜ͱɺ࣌ʑͰ͍͍͔Βɺࢥ͍ग़͍ͯͩ͘͠͞ › ҙͷϝλσʔλΛՃͰ͖Δ͕ɺ୯ͳΔϝλσʔλ › ઐ༻ͷπʔϧ͕Ͱ͖ͨΒ͘ͳΔ͔ 20 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ ྫɿ දݱՄೳͳঢ়ଶԿ௨Γʁ @dataclass class Snack: name:
str # 3 ௨Γ condiments: set[str] # 4 ௨Γ error_code: int # 6 ௨Γʢޭ͕ 0 Τϥʔ͕ 1 ͔Β 5ʣ disposed_of: bool # 2 ௨Γ snack = Snack("Hotdog", {"Mustard", "Ketchup"}, 5, False) ͑ɿ3 ˆ 4 ˆ 6 ˆ 2 = 144 ௨ΓɻNone ڐ༰͢Δͱʁ 21 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ ྫɿ දݱՄೳͳঢ়ଶԿ௨Γʁ @dataclass class Snack: name:
str # 3 ௨Γ condiments: set[str] # 4 ௨Γ @dataclass class Error: error_code: int # 5 ௨ΓʢޭύλʔϯΛऔΓআ͚Δʣ disposed_of: bool # 2 ௨Γ snack: Union[Snack, Error] = Snack("Hotdog", {"Mustard", "Ketchup"}) ͑ɿ3 ˆ 4 + 5 ˆ 2 = 22 ௨Γɻ 22 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 5 ষ ίϨΫγϣϯܕ › ಉछίϨΫγϣϯͱҟछίϨΫγϣϯͷ֓೦Λཧղ͠Α͏ ಉछίϨΫγϣϯ
֨ೲ͞Εͨͯ͢ͷ͕ಉ͡σʔλܕͰ͋ΔίϨΫγϣϯ ҟछίϨΫγϣϯ ҟͳΔσʔλܕΛؚΉίϨΫγϣϯ 23 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ యܕతͳྫɿJSON Λࣙॻʹม͢Δ › dict[str, Union[str, int,
float, None]] ͷΑ͏ͳܕॻ͖ͨ͘ͳ͍ʂ › dict[str, Any] Ͱܕώϯτ͕ܗͳͩ͠ʂ ͦΜͳ࣌ TypedDict ܕώϯτΛଂͨࣙ͠ॻ ͦΜͳ࣌ dataclass ࣗͰ JSON ͷܗࣜΛ੍ޚͰ͖ΔͳΒ dataclass ͕Α͍ɻ 24 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 6 ষ ܕνΣοΧͷΧελϚΠζ › mypy Ͱ
Optional None ʹؔ͢ΔνΣοΫΛ༗ޮʹ͢Δͱྑ͍Α › mypy ͕͍ʁ ͳΒσʔϞϯϞʔυϦϞʔτΩϟογϡͰߴԽ͠Α͏ ܕνΣοΧ mypy ͚ͩ͡Όͳ͍ Pyre Facebook ɺ੩తղੳπʔϧ Pysa ͍ͭͯ͘Δ Pyright Microsoft ɺVSCode ֦ுͷ Pylance ͷϕʔε 25 / 46
ୈ I ෦ ܕΞϊςʔγϣϯ 7 ষ ࣮ફతͳܕνΣοΫͷಋೖ ϖΠϯϙΠϯτΛಛఆͯ͠ίετΛ͔͚ա͗ͣʹܕώϯτΛ͍ΕΑ͏ ·͔ͣ͜͜Β ›
৽نίʔυͷΈܕώϯτ › ϘτϜΞοϓʢϢʔςΟϦςΟɺϥΠϒϥϦʣʹܕώϯτ › རӹΛੜΈग़͢ϏδωεϩδοΫʹܕώϯτ › Α͘ॻ͖͑Δॴʹܕώϯτ › ෳࡶͳ෦ʹܕώϯτ › MonkeyType Pytype Ͱࣗಈతʹ༩༗ޮ͔ 26 / 46
ୈ II ෦ Ϣʔβఆٛܕ 8 ষ ྻڍܕ ੩తͳͷίϨΫγϣϯ͔ΒΛ 1 ͚ͭͩදݱ͍ͨ͠߹ʹ͏
ྻڍܕͷΞϯνύλʔϯ › ಈతʹ͕มԽ͢ΔྻڍܕɻࣙॻΛ͓͏ɻ › IntEnum IntFlag ޙํޓੑͷͨΊʹ͏ɻ৽نʹ͏ͷόάͷݩɻ 27 / 46
ୈ II ෦ Ϣʔβఆٛܕ 9 ষ σʔλΫϥε Python ͷੈքΛେ͖͘ม͑ͨσʔλΫϥεʢݪஶऀҰԡ͠ʣ σʔλΫϥεͷ͍Ͳ͜Ζ
› ҟछίϨΫγϣϯσʔλΫϥεɺࣙॻಉछίϨΫγϣϯ › TypedDict ͱσʔλΫϥεɺ·ͣσʔλΫϥεΛݕ౼͠Α͏ › namedtuple ޙํޓੑͷͨΊʹ͏ σʔλΫϥεສೳͳͷ͔ʁ › σʔλΫϥεଐੑಉ͕࢜ಠཱ͍ͯ͠Δ߹ͷΈ༗ޮ 28 / 46
ୈ II ෦ Ϣʔβఆٛܕ 10 ষ Ϋϥε › ܅Ϋϥεͷຊͷ͍Ͳ͜ΖΛ͍ͬͯΔ͔ ›
ΫϥεͱɺෆมࣜͰ͋Δʢචऀͷςʔθʣ 29 / 46
ୈ II ෦ Ϣʔβఆٛܕ 11 ষ ΠϯλϑΣʔε › ͍͍͢ΠϯλϑΣʔεͱ ›
͜ͷষ؍೦తͰ͋Δ ͍͍͢ΠϯλϑΣʔεΛٴ͢Δ › ར༻ऀͷΑ͏ʹߟ͑ΔʢTDDɺREADME ۦಈ։ൃɺϢʔβϏϦςΟςετʣ › ಛघϝιουɺίϯςΩετϚωʔδϟͷ׆༻ 30 / 46
ୈ II ෦ Ϣʔβఆٛܕ 12 ষ ෦ܕ › ܧঝஔՄೳੑʢLiskov ͷஔݪଇʣʹҙ͢Δ
› ܧঝΑΓίϯϙδγϣϯʢ߹ʣ ਖ਼ํܗํܗ͔ʁ › ֶతʹɺਖ਼ํܗํܗͰ͋Δɻ › ਖ਼ํܗΛํܗͷܧঝͱͯ͠ද͢ͱഁ͢Δɻ ɿਖ਼ํܗͱํܗͷఆٛΛड़Αɻ·ͨɺ໋ʮਖ਼ํܗํܗͰ͋ΔʯΛਖ਼ํܗͱ ํܗͷఆٛʹج͍ͮͯূ໌ͤΑɻ 31 / 46
ୈ II ෦ Ϣʔβఆٛܕ 13 ষ ϓϩτίϧ › ੩తܕνΣοΧͷ݀ΛຒΊΔଘࡏ ›
μοΫλΠϐϯάͱ੩తܕνΣοΧΛͭͳ͙ϓϩτίϧ › ߏత෦ܕͱ໊త෦ܕΛͭͳ͙ϓϩτίϧ 32 / 46
ୈ II ෦ Ϣʔβఆٛܕ ߏత෦ܕɿσʔλܕͷߏΛجૅͱ͢Δ෦ܕ class ShuffleIterator: def __iter__(self): ...
def __next__(self): ... ໊త෦ܕɿσʔλܕͷ໊લΛجૅͱ͢Δ෦ܕ class ShuffleIterator(Iterator): ... 33 / 46
ୈ II ෦ Ϣʔβఆٛܕ 14 ষ pydantic ʹΑΔ࣮ߦ࣌ܕνΣοΫ › ੩తܕνΣοΧͷ݀ΛຒΊΔଘࡏ
› ࣗવʹೖྗͳͲΛνΣοΫͰ͖Δ pydantic ύʔεϥΠϒϥϦͰ͋Δ › int ͳΒ “123” 5.5 int ʹม͢Δ › StrictInt ͳͲΛ͏ඞཁ͋Δ͔ 34 / 46
ୈ III ෦ େنͳมߋͷରԠ 15 ষ ֦ுੑ › ֦ுੑͱɺγεςϜͷطଘ෦Λมߋͤͣʹ৽ػೳΛՃͰ͖Δͱ͍͏γες Ϝͷੑ࣭
› ։์ดͷݪଇ͕ϕʔεʢͲͪΒ͕ઌͩΖ͏͔ʁʣ ݪଇҧͷݟ͚ͭํ › ؆୯ͳ͜ͱ͕͘͠ͳ͍ͬͯͳ͍͔ › ྨࣅͷػೳͷ࣮͕Ε͍ͯͳ͍͔ › ݟੵΓ͕͍ͭେنʹͳ͍ͬͯͳ͍͔ › ίϛοτʹେنͳؚ͕ࠩ·Ε͍ͯͳ͍͔ 35 / 46
ୈ III ෦ େنͳมߋͷରԠ 16 ষ ґଘؔ ґଘؔ 3 छྨ͋Δ
› ཧతґଘؔ › ཧతґଘؔ › ࣌ؒతґଘؔ ґଘؔΛՄࢹԽͤΑ › αʔυύʔςΟϥΠϒϥϦಉ࢜ͷґଘؔ › ΠϯϙʔτϞδϡʔϧؒͷґଘؔ › ؔͷݺͼग़͠ͷՄࢹԽ 36 / 46
ୈ III ෦ େنͳมߋͷରԠ 17 ষ ίϯϙʔβϏϦςΟ ίʔυΛϙϦγʔͱϝΧχζϜʹͤΑ ϙϦγʔ ϏδωεχʔζΛղܾ͢ΔͨΊͷͷΛ୲͏ίʔυ
ϝΧχζϜ ϙϦγʔΛ࣮ݱ͢ΔΈΛఏڙ͢Δίʔυ 37 / 46
ୈ III ෦ େنͳมߋͷରԠ ྫɿ ϙϦγʔͱϝΧχζϜͷ def repeat(times: int =
1) -> collections.abc.Callable def _repeat(func: collections.abc.Callable): @functools.wrap(func) def _wrapper(*args, **kwargs): for _ in range(times): func(*args, **kwargs) return _wrapper return _repeat ϝΧχζϜʢؔΛ܁Γฦ͠ݺͼग़͢ʣͱϙϦγʔʢؔͷதʣΛσίϨʔλͰ ͢Δɻ 38 / 46
ୈ III ෦ େنͳมߋͷରԠ 18 ষͱ 19 ষ 15 ষʮ֦ுੑʯ
ɺ16 ষʮґଘؔʯ ɺ17 ষʮίϯϙʔβϏϦςΟʯͷ۩ମྫͱͯ͠ಡ ͏ɻ ۩ମతͳઃܭʹ͍ͭͯΦϥΠϦʔ͔Β͍͍ຊ͕ͰΔΒ͍͠...ʁ 39 / 46
ୈ IV ෦ ηʔϑςΟωοτͷߏங 20 ষ ੩తղੳ ੩తղੳ ຊॻͰ Pylint
͕հ͞Ε͍ͯΔ͕ɺݸਓతʹ flake8 ͕Α͍ͱࢥͬ ͍ͯΔɻ ෳࡶνΣοΧ MeCabe ͷ॥తෳࡶɺۭനώϡʔϦεςΟΫε ηΩϡϦςΟ Bandit ੩తղੳ͚ͩʹߜ͍͚ͬͯͳ͍ ෳͷղੳπʔϧΛಋೖͯ͠ӴઢΛෳߏங͠Α͏ 40 / 46
ୈ IV ෦ ηʔϑςΟωοτͷߏங 21 ষ ςετઓུ ҎԼͷ 2 ΛಡΜͰ͍ΔਓʹͷͨΓͳ͍͔͠Εͳ͍ɻ
› ςετۦಈ Pythonʢᠳӭࣾʣ › ୯ମςετͷߟ͑ํʗ͍ํʢϚΠφϏग़൛ʣ pytest Λ͏ͱࣗવʹ࣮ફͰ͖Δ͔͠Εͳ͍ 41 / 46
ୈ IV ෦ ηʔϑςΟωοτͷߏங 22 ষ ड͚ೖΕςετ Gherkin ݴޠΛհ͍ͯ͠Δ͕ɺݸਓతʹͲ͏ͩΖ͏ɺͱ͍͏ɻ ͋ΔϓϩάϥϚͷࢥ͍ग़
աڈɺࣄΛ࢝Ί͔ͨΓͷࠒɺ·ͱʹϓϩάϥϛϯά͕Ͱ͖ͳ͍ঢ়ଶͰ BDD Cucumber ΛؚΉ Ruby on Rails ͷνϡʔτϦΞϧΛಡΜͰɺBDD Cucumber ͕ۤखʹͳͬͨɻͦΕΛະͩʹҾ͖͍ͣͬͯΔͷ͔͠Εͳ͍ɻ 42 / 46
ୈ IV ෦ ηʔϑςΟωοτͷߏங 23 ষ ϓϩύςΟϕʔεςετ Hypothesis ʹΑΔϓϩύςΟϕʔεςετͷհ ϓϩύςΟϕʔεςετͱ
ݻఆͨ͠ೖग़ྗʹجͮ͘ςετͰͳ͘ɺೖग़ྗ͕ຬ͖ͨ͢ੑ࣭Λهड़͢Δςετɻ ͦͷੑ࣭Λຬͨ͢Λπʔϧ͕ࣗಈੜͯ͠ςετέʔεΛੜ͢Δɻ 43 / 46
ୈ IV ෦ ηʔϑςΟωοτͷߏங 24 ষ ϛϡʔςʔγϣϯςετ mutmut ʹΑΔϛϡʔςʔγϣϯςετͷհ ϛϡʔςʔγϣϯςετͱ
ςετࣗମΛςετ͢ΔςετɻιʔείʔυΛπʔϧͰॻ͖͑ͯطଘͷςετΛ Βͤͯɺςετ͕ޭͯ͠͠·ͬͨͷΛᖰΓͩ͢ɻ 44 / 46
·ͱΊ ʰϩόετ Pythonʱ͕ݴ͍͍ͨ͜ͱ › σʔλܕͱίϛϡχέʔγϣϯखஈͰ͋Δ › ͕ࣗίʔυͰදݱ͍ͨ͜͠ͱΛσʔλܕΛͬͯ໌֬ʹ͑Α͏ 45 / 46
·ͱΊ ͬͦ͘͞ߪೖ͠Α͏ › https://www.oreilly.co.jp/books/9784814400171/ › https://www.ohmsha.co.jp/book/9784814400171/ ΦϥΠϦʔֶशϓϥοτϑΥʔϜͱ › https://www.oreilly.co.jp/online-learning/ ›
6 ສҎ্ͷॻ੶ʢຊޠॻ੶͋Δʂʣ › 3 ສ࣌ؒҎ্ͷಈը › ۀքΤΩεύʔτʹΑΔϥΠϒΠϕϯτ › ΠϯλϥΫςΟϒͳγφϦΦͱαϯυϘοΫεΛ࣮ͬͨફతͳֶश › ެࣜೝఆࢼݧରࡦࢿྉ › ʰϩόετ PythonʱΦϥΠϦʔֶशϓϥοτϑΥʔϜͰಡΈ์ʢ༧ఆʣ 46 / 46