Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to Write Robust Python Code

How to Write Robust Python Code

HayaoSuzuki

May 29, 2023
Tweet

More Decks by HayaoSuzuki

Other Decks in Technology

Transcript

  1. ݎ࿚ͳ Python ίʔυΛॻ͘ํ๏
    ʰϩόετ PythonʱΛಡ΋͏
    Hayao Suzuki
    BPStudy#189
    May 29, 2023

    View Slide

  2. Who am I ?
    ͓લ୭Α
    ໊લ Hayao Suzukiʢླ໦ɹॣʣ
    Twitter @CardinalXaro
    ࢓ࣄ Software Developer @ BeProud Inc.
    › גࣜձࣾϏʔϓϥ΢υ
    › IT ษڧձࢧԉαʔϏε connpass
    › ΦϯϥΠϯֶशαʔϏε PyQ
    › γεςϜ։ൃͷͨΊͷυΩϡϝϯταʔϏε Tracery
    › 2023 ೥ 5 ݄ 23 ೔ʹ૑ཱ 17 प೥Λܴ͑ͨ
    2 / 46

    View Slide

  3. 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

    View Slide

  4. 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

    View Slide

  5. ࠓ೔ͷςʔϚ
    ݪஶʰRobust Pythonʱ
    ஶऀ Patrick Viafore
    ग़൛ࣾ O’Reilly Media
    ൃߦ೔ 2021 ೥ 7 ݄
    ๜༁ʰϩόετ Pythonʱ
    ຋༁ऀ ླ໦ ॣ ؂༁ɺ௕ඌ ߴ߂ ༁
    ग़൛ࣾ O’Reilly Japan
    ൃߦ೔ 2023 ೥ 3 ݄
    ௕ඌ͞Μɺླ໦ͷϖΞ͸ʰೖ໳ Python 3 ୈ 2 ൛ʱҎདྷ 2 ճ໨
    5 / 46

    View Slide

  6. ࠓ೔ͷςʔϚ
    ʰϩόετ PythonʱΛಡ΋͏
    › ͬ͟ͱɺͲΜͳࣄ͕ॻ͍ͯ͋Δͷ͔঺հ͠·͢
    › 384 ϖʔδͷ಺༰Λ 30 ෼ͰಡΜͩؾ෼ʹͳΖ͏ʂ
    6 / 46

    View Slide

  7. ϩόετ Python ͷߏ੒
    4 ෦ߏ੒
    ୈ I ෦ ܕΞϊςʔγϣϯ
    ୈ II ෦ Ϣʔβఆٛܕ
    ୈ III ෦ େن໛ͳมߋ΁ͷରԠ
    ୈ IV ෦ ηʔϑςΟωοτͷߏங
    ͳ͓ɺୈ 1 ষʮϩόετ Python ೖ໳ʯ͸ಋೖͱͳΔষ
    7 / 46

    View Slide

  8. ैདྷͷٕज़ॻͱͷҧ͍
    Python ͱܕώϯτ
    › ܕώϯτ͸ Python 3.5 ͰಋೖʢPEP 484ʣ
    › Python 3.5 ͸ 2015 ೥ 9 ݄ʹϦϦʔε
    ܕώϯτͷ෇͚ํ͸͢Ͱʹ஌ͬͯΔΑ
    › ܕώϯτͷ෇͚ํͷղઆهࣄ΍ॻ੶͸ଟ͍ʢ8 ೥ͷ஝ੵʣ
    › ܕώϯτͷӡ༻ํ๏΍ߟ͑ํʹ౿ΈࠐΜͩຊ͸ଘࡏ͢Δͷ͔
    ͦ΋ͦ΋ɺதڃऀҎ্޲͚ͷ Python ຊͷઈର਺͕গͳ͍ΑͶ
    8 / 46

    View Slide

  9. ϩόετ Python ͷ͕͍͜͜͢͝
    ϩόετ Python ͷಛ௃
    › ܕώϯτʹ͍ͭͯ 14 ষʹΘͨͬͯৄࡉʹղઆʢୈ I ෦ɺୈ II ෦ʣ
    › ϩόετͳઃܭ࿦ʢୈ III ෦ʣ
    › ܕώϯτ΍ܕ͚ͩͰ͸Χόʔ͖͠Εͳ͍ཁૉ΋ରԠʢୈ IV ෦ʣ
    9 / 46

    View Slide

  10. ϩόετ Python ͷओ୊
    ʰϩόετ Pythonʱ͕ݴ͍͍ͨ͜ͱ
    › σʔλܕͱ͸ίϛϡχέʔγϣϯखஈͰ͋Δ
    › ࣗ෼͕ίʔυͰදݱ͍ͨ͜͠ͱΛσʔλܕΛ࢖ͬͯ໌֬ʹ఻͑Α͏
    10 / 46

    View Slide

  11. ୈ 1 ষ ϩόετ Python ೖ໳
    ϩόετ Python ͬͯͲΜͳຊ
    ཁ͢Δʹɺຊॻ͸ϩόετʢؤৎ/ؤ݈/ݎ࿚ʣͳ Python Λॻͨ͘ΊͷຊͰ͋Δɻ
    ʢP. 1ʣ
    ͦ΋ͦ΋ϩόετͬͯԿʁ
    ίʔυϕʔεͷϩόετωεͱ͸ɺઈ͑ͣมԽͯ͠΋଱ٱੑ͕ߴ͘ɺΤϥʔΛى͜͞ͳ
    ͍͜ͱͰ͋Δɻ
    ʢP. 4ʣ
    11 / 46

    View Slide

  12. ୈ 1 ষ ϩόετ Python ೖ໳
    ͳͥϩόετʹ͢Δඞཁ͕͋Δͷ͔ʁ
    ͦͷ౴͑ͷ֩৺͸ίϛϡχέʔγϣϯʹ͋Δɻ
    ʢதུʣͦͷͨΊʹ͸ɺকདྷͷϝϯςφ
    ͱ௚઀ձΘͳͯ͘΋ࣗ෼ͷ࿦ڌͱҙਤ͕఻ΘΔΑ͏ʹ͍ͨ͠ɻ
    12 / 46

    View Slide

  13. ୈ 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

    View Slide

  14. ୈ 1 ষ ϩόετ Python ೖ໳
    ίϛϡχέʔγϣϯͷ෼ྨ
    ۙ઀ੑ ৘ใͷൃ৴ऀͱड৴ऀͷؒʹ͋Δ࣌ؒతͳڑ཭
    ίετ ίϛϡχέʔγϣϯʹඞཁͳ࿑ྗ
    14 / 46

    View Slide

  15. ୈ 1 ষ ϩόετ Python ೖ໳
    ͳͥϩόετʹ͢Δඞཁ͕͋Δͷ͔ʁ
    ͦͷ౴͑ͷ֩৺͸ίϛϡχέʔγϣϯʹ͋Δɻ
    ʢதུʣͦͷͨΊʹ͸ɺকདྷͷϝϯςφ
    ͱ௚઀ձΘͳͯ͘΋ࣗ෼ͷ࿦ڌͱҙਤ͕఻ΘΔΑ͏ʹ͍ͨ͠ɻ
    ͦͷͨΊʹ͸ʁ
    ະདྷͷϝϯςφʹҙਤΛ఻͑Δʹ͸ɺ௿ίετͰۙ઀ੑ͕ෆཁͳίϛϡχέʔγϣϯ͕
    ඞཁͰ͋Δɻ
    15 / 46

    View Slide

  16. ୈ 1 ষ ϩόετ Python ೖ໳
    ௿ίετͰۙ઀ੑ͕ෆཁͳίϛϡχέʔγϣϯ
    › ίʔυΛಡΉ͚ͩͰཧղͰ͖Ε͹Α͍
    › ίʔυΛཧղ͢Δͷʹඞཁͳ࣌ؒΛ࠷খݶʹ཈͍͑ͨ
    ͦͷͨΊʹ͸ʁ
    σʔλܕͷબ୒͸কདྷͷ։ൃऀʹରͯࣗ͠෼ͷҙਤΛදݱ͢Δ͜ͱͰ͋Γɺਖ਼͍͠σʔ
    λܕΛબ୒͢Ε͹อकੑ͕޲্͢Δɻ
    ʢP. 19ʣ
    16 / 46

    View Slide

  17. ୈ 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

    View Slide

  18. ୈ I ෦ ܕΞϊςʔγϣϯ
    2 ষ Python σʔλܕೖ໳
    › Python ͸ڧ͍ܕ෇͚ݴޠ
    › Python ͸ಈతܕ෇͚ݴޠ
    ಈతܕ෇͚ݴޠ͸ຊ࣭తʹϩόετͰ͸ͳ͍ͷ͔
    › ಈతܕ෇͚ݴޠͰ΋ϩόετʹॻ͚Δɺগ͠େมͳ͚ͩ
    › ੩తܕ෇͚ݴޠͷ৔߹ΑΓ΋Α͘ߟ͑Δඞཁ͕͋Δ
    › ੩తܕ෇͚ݴޠΛ࢖͑͹ඞͣ͠΋ϩόετʹॻ͚ΔΘ͚Ͱ͸ͳ͍
    18 / 46

    View Slide

  19. ୈ I ෦ ܕΞϊςʔγϣϯ
    3 ষ ܕΞϊςʔγϣϯ
    › ܕώϯτͷߏจతͳ෇͚ํ͸஌͍ͬͯΔΑͶʢ8 ೥ͷ஝ੵʣ
    › ܕώϯτ͸πʔϧʢmypy ͳͲʣͱ૊Έ߹ΘͤͯਅՁΛൃش͢Δ
    ܕώϯτ΋ mypy ΋λμͰ͸ͳ͍
    › ެ։ APIɺϥΠϒϥϦͷΤϯυϙΠϯτ
    › ෳࡶͳܕɺΘ͔Γʹ͍͘ܕ
    › mypy ઌੜͷࢦࣔʹै͏
    19 / 46

    View Slide

  20. ୈ I ෦ ܕΞϊςʔγϣϯ
    4 ষ ܕ੍໿
    › Optional Ͱ͵ΔΆόάΛ௵ͦ͏
    › Union ͰදݱՄೳͳঢ়گΛݮͦ͏
    › Literal Ͱ͞Βʹ੍໿Λ͔͚Α͏
    › Final Ͱఆ਺Ͱ͋Δͱओு͠Α͏
    › NewType ͰજࡏతͳόάΛ௵ͦ͏
    Annotated ͷ͜ͱɺ࣌ʑͰ͍͍͔Βɺࢥ͍ग़͍ͯͩ͘͠͞
    › ೚ҙͷϝλσʔλΛ௥ՃͰ͖Δ͕ɺ୯ͳΔϝλσʔλ
    › ઐ༻ͷπʔϧ͕Ͱ͖ͨΒ೤͘ͳΔ͔΋
    20 / 46

    View Slide

  21. ୈ 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

    View Slide

  22. ୈ 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

    View Slide

  23. ୈ I ෦ ܕΞϊςʔγϣϯ
    5 ষ ίϨΫγϣϯܕ
    › ಉछίϨΫγϣϯͱҟछίϨΫγϣϯͷ֓೦Λཧղ͠Α͏
    ಉछίϨΫγϣϯ
    ֨ೲ͞Εͨ͢΂ͯͷ஋͕ಉ͡σʔλܕͰ͋ΔίϨΫγϣϯ
    ҟछίϨΫγϣϯ
    ҟͳΔσʔλܕΛؚΉίϨΫγϣϯ
    23 / 46

    View Slide

  24. ୈ I ෦ ܕΞϊςʔγϣϯ
    యܕతͳྫɿJSON Λࣙॻʹม׵͢Δ
    › dict[str, Union[str, int, float, None]] ͷΑ͏ͳܕ͸ॻ͖ͨ͘ͳ͍ʂ
    › dict[str, Any] Ͱ͸ܕώϯτ͕ܗͳͩ͠ʂ
    ͦΜͳ࣌͸ TypedDict
    ܕώϯτΛ಺ଂͨࣙ͠ॻ
    ͦΜͳ࣌͸ dataclass
    ࣗ෼Ͱ JSON ͷܗࣜΛ੍ޚͰ͖ΔͳΒ dataclass ͕Α͍ɻ
    24 / 46

    View Slide

  25. ୈ I ෦ ܕΞϊςʔγϣϯ
    6 ষ ܕνΣοΧͷΧελϚΠζ
    › mypy Ͱ͸ Optional ΍ None ʹؔ͢ΔνΣοΫΛ༗ޮʹ͢Δͱྑ͍Α
    › mypy ͕஗͍ʁ ͳΒ͹σʔϞϯϞʔυ΍ϦϞʔτΩϟογϡͰߴ଎Խ͠Α͏
    ܕνΣοΧ͸ mypy ͚ͩ͡Όͳ͍
    Pyre Facebook ੡ɺ੩తղੳπʔϧ Pysa ΋͍ͭͯ͘Δ
    Pyright Microsoft ੡ɺVSCode ֦ுͷ Pylance ͷϕʔε
    25 / 46

    View Slide

  26. ୈ I ෦ ܕΞϊςʔγϣϯ
    7 ষ ࣮ફతͳܕνΣοΫͷಋೖ
    ϖΠϯϙΠϯτΛಛఆͯ͠ίετΛ͔͚ա͗ͣʹܕώϯτΛ͍ΕΑ͏
    ·ͣ͸͔͜͜Β
    › ৽نίʔυͷΈܕώϯτ
    › ϘτϜΞοϓʢϢʔςΟϦςΟɺϥΠϒϥϦʣʹܕώϯτ
    › རӹΛੜΈग़͢ϏδωεϩδοΫʹܕώϯτ
    › Α͘ॻ͖׵͑Δ৔ॴʹܕώϯτ
    › ෳࡶͳ෦෼ʹܕώϯτ
    › MonkeyType ΍ Pytype Ͱࣗಈతʹ෇༩΋༗ޮ͔΋
    26 / 46

    View Slide

  27. ୈ II ෦ Ϣʔβఆٛܕ
    8 ষ ྻڍܕ
    ੩తͳ஋ͷίϨΫγϣϯ͔Β஋Λ 1 ͚ͭͩදݱ͍ͨ͠৔߹ʹ࢖͏
    ྻڍܕͷΞϯνύλʔϯ
    › ಈతʹ஋͕มԽ͢ΔྻڍܕɻࣙॻΛ࢖͓͏ɻ
    › IntEnum ΍ IntFlag ͸ޙํޓ׵ੑͷͨΊʹ࢖͏ɻ৽نʹ࢖͏ͷ͸όάͷݩɻ
    27 / 46

    View Slide

  28. ୈ II ෦ Ϣʔβఆٛܕ
    9 ষ σʔλΫϥε
    Python ͷੈքΛେ͖͘ม͑ͨσʔλΫϥεʢݪஶऀҰԡ͠ʣ
    σʔλΫϥεͷ࢖͍Ͳ͜Ζ
    › ҟछίϨΫγϣϯ͸σʔλΫϥεɺࣙॻ͸ಉछίϨΫγϣϯ
    › TypedDict ͱσʔλΫϥε͸ɺ·ͣ͸σʔλΫϥεΛݕ౼͠Α͏
    › namedtuple ͸ޙํޓ׵ੑͷͨΊʹ࢖͏
    σʔλΫϥε͸ສೳͳͷ͔ʁ
    › σʔλΫϥε͸ଐੑಉ͕࢜ಠཱ͍ͯ͠Δ৔߹ͷΈ༗ޮ
    28 / 46

    View Slide

  29. ୈ II ෦ Ϣʔβఆٛܕ
    10 ষ Ϋϥε
    › ܅͸Ϋϥεͷຊ౰ͷ࢖͍Ͳ͜ΖΛ஌͍ͬͯΔ͔
    › Ϋϥεͱ͸ɺෆมࣜͰ͋Δʢචऀͷςʔθʣ
    29 / 46

    View Slide

  30. ୈ II ෦ Ϣʔβఆٛܕ
    11 ষ ΠϯλϑΣʔε
    › ࢖͍΍͍͢ΠϯλϑΣʔεͱ͸
    › ͜ͷষ͸΍΍؍೦తͰ͋Δ
    ࢖͍΍͍͢ΠϯλϑΣʔεΛ௥ٴ͢Δ
    › ར༻ऀͷΑ͏ʹߟ͑ΔʢTDDɺREADME ۦಈ։ൃɺϢʔβϏϦςΟςετʣ
    › ಛघϝιουɺίϯςΩετϚωʔδϟͷ׆༻
    30 / 46

    View Slide

  31. ୈ II ෦ Ϣʔβఆٛܕ
    12 ষ ෦෼ܕ
    › ܧঝ͸ஔ׵ՄೳੑʢLiskov ͷஔ׵ݪଇʣʹ஫ҙ͢Δ
    › ܧঝΑΓ΋ίϯϙδγϣϯʢ߹੒ʣ
    ਖ਼ํܗ͸௕ํܗ͔ʁ
    › ਺ֶతʹ͸ɺਖ਼ํܗ͸௕ํܗͰ͋Δɻ
    › ਖ਼ํܗΛ௕ํܗͷܧঝͱͯ͠ද͢ͱഁ୼͢Δɻ
    ໰ɿਖ਼ํܗͱ௕ํܗͷఆٛΛड़΂Αɻ·ͨɺ໋୊ʮਖ਼ํܗ͸௕ํܗͰ͋ΔʯΛਖ਼ํܗͱ
    ௕ํܗͷఆٛʹج͍ͮͯূ໌ͤΑɻ
    31 / 46

    View Slide

  32. ୈ II ෦ Ϣʔβఆٛܕ
    13 ষ ϓϩτίϧ
    › ੩తܕνΣοΧͷ݀ΛຒΊΔଘࡏ
    › μοΫλΠϐϯάͱ੩తܕνΣοΧΛͭͳ͙ϓϩτίϧ
    › ߏ଄త෦෼ܕͱ໊໨త෦෼ܕΛͭͳ͙ϓϩτίϧ
    32 / 46

    View Slide

  33. ୈ II ෦ Ϣʔβఆٛܕ
    ߏ଄త෦෼ܕɿσʔλܕͷߏ଄Λجૅͱ͢Δ෦෼ܕ
    class ShuffleIterator:
    def __iter__(self):
    ...
    def __next__(self):
    ...
    ໊໨త෦෼ܕɿσʔλܕͷ໊લΛجૅͱ͢Δ෦෼ܕ
    class ShuffleIterator(Iterator):
    ...
    33 / 46

    View Slide

  34. ୈ II ෦ Ϣʔβఆٛܕ
    14 ষ pydantic ʹΑΔ࣮ߦ࣌ܕνΣοΫ
    › ੩తܕνΣοΧͷ݀ΛຒΊΔଘࡏ
    › ࣗવʹೖྗ஋ͳͲΛνΣοΫͰ͖Δ
    pydantic ͸ύʔεϥΠϒϥϦͰ΋͋Δ
    › int ͳΒ͹ “123” ΋ 5.5 ΋ int ʹม׵͢Δ
    › StrictInt ͳͲΛ࢖͏ඞཁ΋͋Δ͔΋
    34 / 46

    View Slide

  35. ୈ III ෦ େن໛ͳมߋ΁ͷରԠ
    15 ষ ֦ுੑ
    › ֦ுੑͱ͸ɺγεςϜͷطଘ෦෼Λมߋͤͣʹ৽ػೳΛ௥ՃͰ͖Δͱ͍͏γες
    Ϝͷੑ࣭
    › ։์ด࠯ͷݪଇ͕ϕʔεʢͲͪΒ͕ઌͩΖ͏͔ʁʣ
    ݪଇҧ൓ͷݟ͚ͭํ
    › ؆୯ͳ͜ͱ͕೉͘͠ͳ͍ͬͯͳ͍͔
    › ྨࣅͷػೳͷ࣮૷͕஗Ε͍ͯͳ͍͔
    › ݟੵ΋Γ͕͍ͭ΋େن໛ʹͳ͍ͬͯͳ͍͔
    › ίϛοτʹେن໛ͳࠩ෼ؚ͕·Ε͍ͯͳ͍͔
    35 / 46

    View Slide

  36. ୈ III ෦ େن໛ͳมߋ΁ͷରԠ
    16 ষ ґଘؔ܎
    ґଘؔ܎͸ 3 छྨ͋Δ
    › ෺ཧతґଘؔ܎
    › ࿦ཧతґଘؔ܎
    › ࣌ؒతґଘؔ܎
    ґଘؔ܎ΛՄࢹԽͤΑ
    › αʔυύʔςΟϥΠϒϥϦಉ࢜ͷґଘؔ܎
    › ΠϯϙʔτϞδϡʔϧؒͷґଘؔ܎
    › ؔ਺ͷݺͼग़͠ͷՄࢹԽ
    36 / 46

    View Slide

  37. ୈ III ෦ େن໛ͳมߋ΁ͷରԠ
    17 ষ ίϯϙʔβϏϦςΟ
    ίʔυΛϙϦγʔͱϝΧχζϜʹ෼཭ͤΑ
    ϙϦγʔ ϏδωεχʔζΛղܾ͢ΔͨΊͷ௚઀ͷ੹೚Λ୲͏ίʔυ
    ϝΧχζϜ ϙϦγʔΛ࣮ݱ͢Δ࢓૊ΈΛఏڙ͢Δίʔυ
    37 / 46

    View Slide

  38. ୈ 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

    View Slide

  39. ୈ III ෦ େن໛ͳมߋ΁ͷରԠ
    18 ষͱ 19 ষ
    15 ষʮ֦ுੑʯ
    ɺ16 ষʮґଘؔ܎ʯ
    ɺ17 ষʮίϯϙʔβϏϦςΟʯͷ۩ମྫͱͯ͠ಡ
    ΋͏ɻ
    ۩ମతͳઃܭ࿦ʹ͍ͭͯ͸ΦϥΠϦʔ͔Β͍͍ຊ͕ͰΔΒ͍͠...ʁ
    39 / 46

    View Slide

  40. ୈ IV ෦ ηʔϑςΟωοτͷߏங
    20 ষ ੩తղੳ
    ੩తղੳ ຊॻͰ͸ Pylint ͕঺հ͞Ε͍ͯΔ͕ɺݸਓతʹ͸ flake8 ͕Α͍ͱࢥͬ
    ͍ͯΔɻ
    ෳࡶ౓νΣοΧ MeCabe ͷ॥؀తෳࡶ౓ɺۭന਺ώϡʔϦεςΟΫε
    ηΩϡϦςΟ Bandit
    ੩తղੳ͚ͩʹߜͬͯ͸͍͚ͳ͍
    ෳ਺ͷղੳπʔϧΛಋೖͯ͠๷ӴઢΛෳ਺ߏங͠Α͏
    40 / 46

    View Slide

  41. ୈ IV ෦ ηʔϑςΟωοτͷߏங
    21 ষ ςετઓུ
    ҎԼͷ 2 ࡭ΛಡΜͰ͍Δਓʹ͸΋ͷͨΓͳ͍͔΋͠Εͳ͍ɻ
    › ςετۦಈ Pythonʢᠳӭࣾʣ
    › ୯ମςετͷߟ͑ํʗ࢖͍ํʢϚΠφϏग़൛ʣ
    pytest Λ࢖͏ͱࣗવʹ࣮ફͰ͖Δ͔΋͠Εͳ͍
    41 / 46

    View Slide

  42. ୈ IV ෦ ηʔϑςΟωοτͷߏங
    22 ষ ड͚ೖΕςετ
    Gherkin ݴޠΛ঺հ͍ͯ͠Δ͕ɺݸਓతʹ͸Ͳ͏ͩΖ͏ɺͱ͍͏ɻ
    ͋ΔϓϩάϥϚͷࢥ͍ग़
    աڈɺ࢓ࣄΛ࢝Ίͨ͹͔Γͷࠒɺ·ͱ΋ʹϓϩάϥϛϯά͕Ͱ͖ͳ͍ঢ়ଶͰ BDD ΍
    Cucumber ΛؚΉ Ruby on Rails ͷνϡʔτϦΞϧΛಡΜͰɺBDD ΍
    Cucumber ͕ۤखʹͳͬͨɻͦΕΛະͩʹҾ͖͍ͣͬͯΔͷ͔΋͠Εͳ͍ɻ
    42 / 46

    View Slide

  43. ୈ IV ෦ ηʔϑςΟωοτͷߏங
    23 ষ ϓϩύςΟϕʔεςετ
    Hypothesis ʹΑΔϓϩύςΟϕʔεςετͷ঺հ
    ϓϩύςΟϕʔεςετͱ͸
    ݻఆͨ͠ೖग़ྗʹجͮ͘ςετͰ͸ͳ͘ɺೖग़ྗ͕ຬͨ͢΂͖ੑ࣭Λهड़͢Δςετɻ
    ͦͷੑ࣭Λຬͨ͢஋Λπʔϧ͕ࣗಈੜ੒ͯ͠ςετέʔεΛੜ੒͢Δɻ
    43 / 46

    View Slide

  44. ୈ IV ෦ ηʔϑςΟωοτͷߏங
    24 ষ ϛϡʔςʔγϣϯςετ
    mutmut ʹΑΔϛϡʔςʔγϣϯςετͷ঺հ
    ϛϡʔςʔγϣϯςετͱ͸
    ςετࣗମΛςετ͢ΔςετɻιʔείʔυΛπʔϧͰॻ͖׵͑ͯطଘͷςετΛ
    ૸Βͤͯɺςετ͕੒ޭͯ͠͠·ͬͨ΋ͷΛᖰΓͩ͢ɻ
    44 / 46

    View Slide

  45. ·ͱΊ
    ʰϩόετ Pythonʱ͕ݴ͍͍ͨ͜ͱ
    › σʔλܕͱ͸ίϛϡχέʔγϣϯखஈͰ͋Δ
    › ࣗ෼͕ίʔυͰදݱ͍ͨ͜͠ͱΛσʔλܕΛ࢖ͬͯ໌֬ʹ఻͑Α͏
    45 / 46

    View Slide

  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

    View Slide