質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
スコープ

スコープとは、プログラム内で変数名など、参照可能な有効範囲のことを指します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

341閲覧

[初心者]Pythonのスコープについて2点質問(バグ・変数と関数の扱い)

go0x

総合スコア13

スコープ

スコープとは、プログラム内で変数名など、参照可能な有効範囲のことを指します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/09/06 06:05

前提・実現したいこと

Pythonの基礎勉強のため、ドラクエのようなゲームを作ろうと思っています。

[3]銀行 を選ぶと500円もらえる設定し、1000 + 500円で所持金は 1500円になる予定ですが、
下記の通り1000円のままになってしまいます。

[質問]
1)本件のバグの原因は何でしょうか?

2)今後内容拡大に伴い関数が増えていくと、コメント # グローバル変数 の箇所のように
様々な部分で global ~ が無数に登場する気がするのですが、
基本的なやり方として別の方法があるのでしょうか?

それとも global ~ はある程度多く使うものでしょうか?

変数と関数の基礎的な扱いがまだよく分かっておらず、初歩的な質問ですがよろしくお願いします。

実行結果

誰と話す?[1]村人[2]武器屋[3]銀行 3 現在の所持金1000円 ここは銀行です これをきみにあげよう 500円を手に入れた! 現在の所持金1000円 誰と話す?[1]村人[2]武器屋[3]銀行

該当のソースコード

python

1 2# 所持金 3money = 1000 4 5# NPC 6npc = {'villager': {'name': "村人", 'quote': "ここは最初の村です"}, 7 'armsshop': {'name': "武器屋", 'quote': "ここは武器屋だ" }, 8 'banker' : {'name': "銀行", 'quote': "ここは銀行です" }} 9 10# 現在のステータス表示 11money_status = "現在の所持金" + str(money) + "円" 12 13def status(): 14 print(money_status) 15 16# 銀行イベント 17def banker_event(): 18 print("これをきみにあげよう") 19 get_money(500) 20 21def get_money(x): 22 global money # グローバル変数 23 print(str(x) + "円を手に入れた!") 24 money += x 25 26# NPCを選択 27choice_txt = "誰と話す?" 28npc_choice = choice_txt + \ 29 "[1]" + npc['villager']['name'] + \ 30 "[2]" + npc['armsshop']['name'] + \ 31 "[3]" + npc['banker']['name'] 32 33def act(): 34 act_number = int(input(npc_choice)) 35 36 if act_number == 1: 37 print(npc['villager']['quote']) 38 elif act_number == 2: 39 print(npc['armsshop']['quote']) 40 elif act_number == 3: 41 print(npc['banker']['quote']) 42 banker_event() 43 44# 実行 45def main(): 46 for _ in range(5): 47 status() 48 act() 49 50main() 51

補足情報(FW/ツールのバージョンなど)

OS:Mac
Editor:Atom

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1)本件のバグの原因は何でしょうか?

money自体は確かに更新されています。
しかし、money_statusの値がmoneyの変化に伴って更新されることはありません。

関数statusを改良すればバグは解消するでしょう。

Python

1def status(): 2 print("現在の所持金" + str(money) + "円")

2)今後内容拡大に伴い関数が増えていくと、コメント # グローバル変数 の箇所のように

様々な部分で global ~ が無数に登場する気がするのですが、
基本的なやり方として別の方法があるのでしょうか?

クラスを作ります。
そうすれば、変数の影響範囲が縮まりますので。

それとも global ~ はある程度多く使うものでしょうか?

バグが蔓延する要因になるので、むしろ一切使わない方法を検討すべきです。

書いてみた

雑な作りですが、クラスを使った例です。

main.py

Python

1from player import Player 2from non_player import choose_event 3 4 5hero = Player(money=1000) 6for _ in range(5): 7 event = choose_event() 8 9 hero.print_status() 10 hero.process_event( 11 event() 12 ) 13 14 print()

player.py

Python

1from event import EventType 2 3 4class Player: 5 def __init__(self, money): 6 self._money = money 7 self._action_table = { 8 EventType.DO_NOTHING: lambda: None, 9 EventType.GET_MONEY: self._add_money, 10 } 11 12 def process_event(self, event): 13 self._action_table[event.event_type](*event.args) 14 15 def print_status(self): 16 print(f'現在の所持金{self._money}') 17 18 def _add_money(self, value): 19 print(f'{value}円を手に入れた!') 20 self._money += value

non_player.py

Python

1from event import Event, EventType 2 3 4class _NonPlayer: 5 def __init__(self, name, event): 6 self.name = name 7 self.event = event 8 9 10def _event_stub(): 11 print('特に用はないよ') 12 return Event(EventType.DO_NOTHING) 13 14def _banker_event(): 15 print('ここは銀行です') 16 print('これをきみにあげよう') 17 return Event(EventType.GET_MONEY, 500) 18 19 20npcs = [ 21 _NonPlayer('村人', _event_stub), 22 _NonPlayer('武器屋', _event_stub), 23 _NonPlayer('銀行屋', _banker_event), 24] 25 26def choose_event(): 27 print('誰と話す?', end='') 28 for i, npc in enumerate(npcs, start=1): 29 print(f'[{i}]{npc.name}', end='') 30 31 num = int(input(' ')) 32 return npcs[num-1].event

event.py

Python

1from enum import Enum, auto 2 3 4class EventType(Enum): 5 DO_NOTHING = auto() 6 GET_MONEY = auto() 7 8 9class Event: 10 def __init__(self, event_type, *args): 11 self.event_type = event_type 12 self.args = args

実行例

plain

1>python main.py 2誰と話す?[1]村人[2]武器屋[3]銀行屋 1 3現在の所持金1000 4特に用はないよ 5 6誰と話す?[1]村人[2]武器屋[3]銀行屋 2 7現在の所持金1000 8特に用はないよ 9 10誰と話す?[1]村人[2]武器屋[3]銀行屋 3 11現在の所持金1000 12ここは銀行です 13これをきみにあげよう 14500円を手に入れた! 15 16誰と話す?[1]村人[2]武器屋[3]銀行屋 2 17現在の所持金1500 18特に用はないよ 19 20誰と話す?[1]村人[2]武器屋[3]銀行屋 3 21現在の所持金1500 22ここは銀行です 23これをきみにあげよう 24500円を手に入れた!

投稿2018/09/06 06:13

編集2018/09/06 06:50
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

go0x

2018/09/06 06:20

迅速な回答ありがとうございます。 >クラスを作ります。 >そうすれば、変数の影響範囲が縮まりますので。 クラスについて読んだり書いたりしているのですが、なかなか活用法が腑に落ちないできないのでよろしければ本件かその他の例でもう少し具体的に教えてもらえませんでしょうか?
go0x

2018/09/06 07:04

サンプルありがとうございます!たった数行のコードでこんなに違うんですね... 全部読み込めてないのでじっくり勉強させてもらいます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問