Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
変数に変数を代入したら?
Search
mizzsugar
July 04, 2020
Programming
1
2.6k
変数に変数を代入したら?
mizzsugar
July 04, 2020
Tweet
Share
More Decks by mizzsugar
See All by mizzsugar
厳しさとゆるさの間で迷う人に捧げる個人開発記
mizzsugar
0
34
SQLModel入門〜クエリと型〜
mizzsugar
2
1.4k
フルリモート向いてないと思っていた私が、なんだかんだ健やかに 1年半フルリモート出来ている話
mizzsugar
1
150
Djangoでのプロジェクトだって型ヒントを運用出来る!
mizzsugar
4
8.9k
「動くものは作れる」の一歩先へ 〜「自走プログラマー」の紹介〜
mizzsugar
0
610
pytestの第一歩 〜「テスト駆動Python」の紹介〜
mizzsugar
3
420
データ分析ツール開発でpoetryを使う選択肢
mizzsugar
1
1.2k
unittest.mockを使ってテストを書こう
mizzsugar
5
6.7k
Djangoのパスワードハッシュアルゴリズムで_PyramidのWebアプリケーション作った.pdf
mizzsugar
0
930
Other Decks in Programming
See All in Programming
【卒業研究】会話ログ分析によるユーザーごとの関心に応じた話題提案手法
momok47
0
160
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
440
Pythonではじめるオープンデータ分析〜書籍の紹介と書籍で紹介しきれなかった事例の紹介〜
welliving
3
750
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
190
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
160
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
0
160
Graviton と Nitro と私
maroon1st
0
160
Developing static sites with Ruby
okuramasafumi
1
340
フルサイクルエンジニアリングをAI Agentで全自動化したい 〜構想と現在地〜
kamina_zzz
0
340
Combinatorial Interview Problems with Backtracking Solutions - From Imperative Procedural Programming to Declarative Functional Programming - Part 2
philipschwarz
PRO
0
130
組み合わせ爆発にのまれない - 責務分割 x テスト
halhorn
1
180
C-Shared Buildで突破するAI Agent バックテストの壁
po3rin
0
430
Featured
See All Featured
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2k
How to Talk to Developers About Accessibility
jct
1
94
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
360
Balancing Empowerment & Direction
lara
5
830
A Modern Web Designer's Workflow
chriscoyier
698
190k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
180
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Visualization
eitanlees
150
16k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
1
220
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
400
Transcript
変数に変数を代入したら? 〜仕組みを知ってハマらないようになろう〜 2020-07-04 Python Charity Talks in Japan @mizzsugar0425 1
前提 • この発表の対象者は初学者です。 • Pythonで変数に変数を代入した時の仕組みを知り、 安全なプログラムを書けるようになることが目的です。 2
お前、誰よ? • みずきと申します。 • Twitter: @mizzsugar0425 • PythonでWebサービスの開発をしています。(Pyramid, Django, PostgreSQL,
Nuxt.js, Angular …) • コーヒーと自転車とPythonが好きです。 3
クイズ① 〜枠の中に入るものは?〜 >>> name_1 = 'aaa' >>> name_2 = name
>>> name_1.replace('a', 'b') 'bbb' >>> name_1 'aaa' >>> name_2 'aaa' 4
クイズ① の答え >>> name_1 = 'aaa' >>> name_2 = name
>>> name_1.replace('a', 'b') 'bbb' >>> name_1 'aaa' >>> name_2 'aaa' 5
クイズ② 〜枠の中に入るものは?〜 >>> list_1 = [1, 2, 3] >>> list_2
= list_1 >>> list_1.append(4) >>> list_1 [1, 2, 3, 4] >>> list_2 [1, 2, 3, 4] 6
クイズ② の答え >>> list_1 = [1, 2, 3] >>> list_2
= l >>> list_1.append(4) >>> list_1 [1, 2, 3, 4] >>> list_2 [1, 2, 3, 4] 7
何故List型の時は変わってしまったのでしょうか? 8
値が変わってしまった理由は オブジェクトの仕組みにあります。 9
Pythonでは全てオブジェクト Pythonでは、int型 str型 List型 … 全てをオブジェクトとして扱います。 10 https://docs.python.org/ja/3/reference/datamodel.html#objects-values-and-types
number = 1 # int型のオブジェクト name = 'Taro' # str型のオブジェクト
names = ['Taro', 'Jiro', 'Saburo'] # List型のオブジェクト class Person: def __init__(self, name: str, age: int) -> None: self.name = name self.age = age person = Person(name='Taro', age=10) # Person型のオブジェクト 11
オブジェクトの識別値を返すid() • 組み込み関数id()はオブジェクトの識別値(identify)を返します。 • id()の値が同じならば同じオブジェクトです。 12
>>> num_1 = 143748927394325 >>> id(num_1) 139627296785840 >>> num_2 =
143748927394325 >>> id(num_2) # numと同じ値だけれども違うオブジェクト 139627296786576 >>> num_1 += 1 # 別のオブジェクトとして値が代入される >>> id(num_1) 139627305196544 13 Pythonでは1や2などよく使われる数値は最適化のために同じ idになります。
副作用とは • 副作用とは、オブジェクトの値を変更することです。 • 副作用を伴う操作を許容するオブジェクトを「ミュータブル」なオブジェクトといいま す。 • 「イミュータブル」なオブジェクトは副作用を許容しません。 14 例:
>>> list_1 = [1, 2] >>> list_1.append(3) >>> list_1 [1, 2, 3]
ミュータブル・イミュータブルなオブジェクト • ミュータブルなオブジェクトの例 List型、Dict型、Set型… のオブジェクト • イミュータブルなオブジェクトの例 int型、str型、Tuple型… のオブジェクト 15
副作用を伴わない操作の場合① >>> name_1 = 'aaa' # str型のイミュータブルなオブジェクト >>> id(name_1) 139720897350384
>>> name_1.replace('a', 'b') # nameとは別オブジェクトを生成する、副作用 のない操作 'bbb' >>> name_1 # 上記のreplaceでname値は変更されていないのでidはそのまま 'aaa' 16
副作用を伴わない操作の場合② >>> name_1 = 'aaa' # str型のイミュータブルなオブジェクト >>> name_2 =
name_1 >>> name_1 = 'bbb' # nameは1行目とは別のオブジェクトになります。 >>> name_2 # str型はイミュータブルなのでname_2には影響はありません。 'aaa' 17
18 name name_2 オブジェク ト① name name_2 オブジェク ト① オブジェク
ト② name = 'bbb'
副作用を伴わない操作の場合③ >>> list_1 = [1, 2, 3] # List型のミュータブルなオブジェクト >>>
list_2 = list_1 + [4] # list_1の値が変わらないイミュータブルな操作 >>> list_2 [1, 2, 3, 4] >>> list_1 [1, 2, 3] 19
副作用を伴わない操作の場合④ >>> id(list_1) 140410856800704 >>> id(list_2) 140410884215232 20
副作用を伴う操作の場合① >>> list_1 = [1, 2, 3] # List型のミュータブルなオブジェクト >>>
id(list_1) 139720897421120 >>> list_1.append(4) # list_1の値を変更する副作用を伴う処理 >>> list_1 [1, 2, 3, 4] >>> id(list_1) # ミュータブルなので値が変わりオブジェクトは同じまま 139720897421120 21
副作用を伴う操作の場合② >>> list_2 = list_1 >>> list_1.append(5) >>> list_1 [1,
2, 3, 4, 5] >>> list_2 # list_1とlist_2は同じオブジェクトを指したままなのでlist_2も 変更 [1, 2, 3, 4, 5] 22
list_2の値が変わらないようにするには copy.copyを使いましょう。 23 >>> list_1 = [1, 2, 3] >>>
list_2 = copy.copy(list_1) >>> list_1.append(4) >>> list_1 [1, 2, 3, 4] >>> list_2 [1, 2, 3]
copy.copyを使うと何が起こるか 代入元の変数の値がコピーされたオブジェクトが渡されて 別のオブジェクトとなります。 24 >>> list_1 = [1, 2, 3]
>>> list_2 = copy.copy(list_1) >>> id(list_1) 140594427010048 >>> id(list_2) 140594427023056
まとめ • 副作用とは、オブジェクトの値を変更することです。 • 副作用を伴う操作を許容しないのがイミュータブルなオブジェクト。 • 副作用を伴う操作を許容するのがミュータブルなオブジェクト。 • ミュータブルな型の変数を別の変数に代入したら 変数の変更が別の変数にも反映されます。
• ミュータブルな変数を別の変数に代入したいならcopy.copyを使いましょう。 ご清聴ありがとうございました。 25
[おまけ] list_1とlist_2の値は何になるでしょうか? >>> def add_number(numbers_list: List[int], number: int) -> List[int]:
... numbers_list.append(number) ... return numbers_list >>> >>> list_1 = [1, 2, 3] >>> list_2 = add_number(l, 4) 26
list_2には値が変わってほしくなかったのに… >> # 正解は… >>> list_1 [1, 2, 3, 4]
>>> list_2 [1, 2, 3, 4] 27
copy.copyで意図しない値の変化を防ぎましょう >>> def add_number(numbers_list: List[int], number: int) -> List[int]: ...
added_list = copy.copy(numbers_list) ... added_list.append(number) ... return added_list 28