Misaku
@Misaku (Misaku suzuki)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

python .pyファイルにすると動かない

解決したいこと

一つのセルで実行すると正常に動作するのですが、
オブジェクト部分を .pyファイルへコピーし
インポートして時効するとエラーになります。

発生している問題・エラー

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Input In [1], in <module>
     11 ticket_number = fan1_ticket_amount
     13 fan1_name = Fan(fan1_name, fan1_sex, fan1_age, {})
---> 15 fan1_name.buy_ticket()
     18 fan1_name.have_ticket()

File ~/environment/Band/fan.py:18, in Fan.buy_ticket(self)
     17 def buy_ticket(self):
---> 18     self.inventory[ticket_band_name] = ticket_number

NameError: name 'ticket_number' is not defined

該当するソースコード

#failname fan.py
class Fan:
    
    def __init__(self, name, sex, age, inventory):
        
        self.name = name
        self.sex = sex
        self.age = age
        self.tickets = 0
        self.level = 1
        self.inventory = {}

    def have_ticket(self):
        print(f"{self.name}の所持しているチケットは")
        print(self.inventory.items())
        
    def buy_ticket(self):
        self.inventory[ticket_band_name] = ticket_number
        
from fan import Fan

fan1_name = input("あなたの名前を入力:")
fan1_sex = input("あなたの性別を入力:")
fan1_age = int(input("あなたの年齢を入力:"))

fan1_buy_ticket = input("チケットを買いたいバンド名:")
ticket_band_name = fan1_buy_ticket

fan1_ticket_amount = int(input("何枚買いますか:"))
ticket_number = fan1_ticket_amount

fan1_name = Fan(fan1_name, fan1_sex, fan1_age, {})

fan1_name.buy_ticket()


fan1_name.have_ticket()

自分で試したこと

.pyに分けず、同じセルで実行すると正常に動きます。。


class Fan:
    
    def __init__(self, name, sex, age, inventory):
        
        self.name = name
        self.sex = sex
        self.age = age
        self.tickets = 0
        self.level = 1
        self.inventory = {}

    def have_ticket(self):
        print(f"{self.name}の所持しているチケットは")
        print(self.inventory.items())
        
    def buy_ticket(self):
        self.inventory[ticket_band_name] = ticket_number
        

fan1_name = input("あなたの名前を入力:")
fan1_sex = input("あなたの性別を入力:")
fan1_age = int(input("あなたの年齢を入力:"))

fan1_buy_ticket = input("チケットを買いたいバンド名:")
ticket_band_name = fan1_buy_ticket

fan1_ticket_amount = int(input("何枚買いますか:"))
ticket_number = fan1_ticket_amount

fan1_name = Fan(fan1_name, fan1_sex, fan1_age, {})

fan1_name.buy_ticket()


fan1_name.have_ticket()

実行結果
スクリーンショット 2022-04-10 23.07.44.png

.pyファイルにオブジェクト部分を分けたいのですがエラーの原因がどうしてもわかりません。
どなたかヒントを教えていただけるとありがたいです。

0

2Answer

原因

クラスFanではticket_band_nameticket_numberを定義していないので,

NameError: name 'ticket_number' is not defined

と未定義であることのエラーが出ています.同一ファイルに書いたときはPythonの仕様でこれらの値をグローバル変数から呼び出せてしまうのでエラーになりませんでした.

改善案

buy_ticketというメソッドに何も情報を渡していないので,上のような書き方は不適切だと考えます.

改善案としては

fan.py
def buy_ticket(self, ticket_band_name, ticket_number):
    self.inventory[ticket_band_name] = ticket_number

のようにしつつそれを呼び出すときには

fan1_name.buy_ticket(ticket_band_name, ticket_number)

としてあげるのが適切に思います.
というかFan()で生成したインスタンスはfan1とかで良さそうなのにfan1_nameになっちゃっているのも気になります.
また,クラスFanの初期化において,引数としてinventoryを用意しているのに,それを使っていません.
self.inventory = inventoryにするべきだと思います.

3Like

Comments

  1. @Misaku

    Questioner

    ありがとうございます!助かりました。

変数名の参照の問題だと思われます。

同ファイルに存在する場合は、ticket_number , ticket_band_name は変数名として有効ですが、別ファイルから呼び出す場合には、上記の変数名は無効です。
print(locals())で有効な変数名について見れるので確認できます。

別ファイルからimport する場合には、以下のいずれかの方法があるかと。

  1. ticket_number , ticket_band_name をbuy_ticketの引数に加える
  2. 上記変数をinitの時点(Fan())で引数に加える
  3. 上記変数をglobal変数にする(非推奨)
2Like

Comments

  1. @Misaku

    Questioner

    ありがとうございます! 助かりました!

Your answer might help someone💌