0

Python 3 でオブジェクト指向プログラミングを学習しようとしています。本にあるノートブック プログラムのバリエーションを作成していますが、ノートブックにメモを追加する代わりに、タイムシートに日数を追加しようとしています。

元のチュートリアルでは、これはメイン プログラムにあります。

def add_note(self):
    memo = input("Enter a memo: ")
    self.notebook.new_note(memo)
    print("Your note has been added")

これはクラスモジュール(ノートブック)にあります:

def new_note(self, memo, tags = ''):
    '''create a new note and add it to the list'''
    self.notes.append(Note(memo,tags=''))

私のバリエーションは次のようになります。

主要:

def add_work_day(self):
        date = input ("Enter date : ")
        hours = input ("Enter hours worked : ")
        rate = input ("Enter hourly rate : £")
        workday = Timesheet.day(date, hours, rate)

モジュール:

class Timesheet:
       def __init__(self):
            self.timesheet = []

        def day(self, date, hours, rate):

        self.timesheet.append(day(date, hours, rate))

それは私にこのエラーを与えています:

File "C:\Python33\timesheet_menu.py", line 39, in add_work_day
    workday = Timesheet.day(date, hours, rate)
TypeError: day() missing 1 required positional argument: 'rate'

「def day(self, date, hours, rate)」の「self」が入力引数の 1 つを占有しているようです。

ここで何が欠けているのか誰か教えてもらえますか?

.....アップデート.....

これで、main に Timesheet() のインスタンスを作成しました。

    def add_work_day(self):
        date = input ("Enter date : ")
        hours = input ("Enter hours worked : ")
        rate = input ("Enter hourly rate : £")
        workday = Timesheet()
        workday.add_day(date, hours, rate) 

しかし、Timesheet() メソッド「day」から新しいエラーが発生しています

class Timesheet:


    def __init__(self):
        self.timesheet = []

    def day(self, date, hours, rate):
        self.timesheet.append(day(date, hours, rate))

File "C:\Python33\timesheet_menu.py", line 40, in add_work_day
workday.add_day(date, hours, rate)
File "C:\Python33\timesheet.py", line 29, in add_day
self.timesheet.append(day(date, hours, rate))
NameError: global name 'day' is not defined

問題が .append(day 部分であることは理解していますが、それを修正する方法がわかりません。変数が指定されていない限りグローバルではないことはわかっていますが、私のロジックはメソッドがそうであるべきだと言っています。 .append(day は、「day」という既存の変数を探しています。このメソッドが本の例で機能したため、混乱しています。

4

3 に答える 3

2

問題の根本は、Python のクラスとインスタンスがどのように機能するかをまだ理解していないことです。

のようなクラスTimesheetは、クラスの名前空間に存在するメソッド (関数) と変数のコレクションです。インスタンスは、クラスの特定のインスタンスです (つまり、存在する他のすべてのタイムシートとは対照的に、このタイムシート)。各インスタンスには独自の名前空間がありますが、これは少し特殊です。インスタンスの名前空間でメソッドまたは変数を探す場合、名前が見つからない場合は、次にクラスの名前空間が検索されます。(また、クラスが他のクラスから継承する場合、名前が見つかるか、検索する名前空間がなくなるまで、その先祖の名前空間が順番に検索されます。)

現在、クラスで定義されたメソッド (関数) には特別な動作がありますが、クラスで定義された関数にはありません。これが、クラスで定義された関数に別の用語 (メソッド) が使用されている理由です。行動。特別な動作は次のとおりです。関数がクラスのインスタンスで呼び出されている場合、そのインスタンスは「追加の」最初のパラメーターとして関数に渡されます。(慣例により、その最初のパラメーターは と呼ばれますがself、それを呼び出せない理由はありませんfhqwhgadsあなたがしたい場合。すべきではありません -- それはコードを読むのを完全に混乱させるだけです -- しかし、あなたが望むならそうすることができます.) なぜその余分な最初のパラメータ? インスタンスには独自の名前空間があると言ったことを覚えていますか? インスタンスの変数を検索する場合 (たとえば、他のタイムシートではなく、このタイムシートのエントリを検索する場合)、インスタンスへの参照が必要です。selfパラメータはその参照を提供します。

ここで、 instanceではなくclassでメソッドを呼び出す場合、クラスへの参照が明らかに既にあるため、追加のパラメーターは必要ありません。その参照は nameです。そのため、他のパラメーターの前に「余分な」最初のパラメーターが追加されることはありません。これは、インスタンスを参照しているのではなく、クラスを参照しているためです。selfTimesheetTimesheet.day(...)

しかし、 を呼び出すTimesheet().day(...)と、2 つのことが起こっています。まず、 のインスタンスTimesheetを作成し(定式化はインスタンスのTimesheet()作成方法です)、次にそのインスタンスday()でメソッドを呼び出しています。したがって、「余分な」最初のパラメーターがメソッドに渡され、内部のコードがそのインスタンスの変数にアクセスできるようになります。day()day()

もう 1 つ理解する必要があるのは、変数がインスタンスに属している場合と、クラスに属している場合です。これを判断するために自問できる非常に簡単な質問があります:「これはすべてのタイムシートに適用されますか、それとも特定のタイムシートのみに適用されますか? メソッドが特定のday()タイムシートの値にアクセスする必要があることは明らかです(Joe は Bob とは異なる時間、異なる賃金で働いていました)。そのため、クラスではなくインスタンスで呼び出す必要があります。したがって、メソッドにパラメーターを含めることは理にかなっていますが、クラスからではなく、メソッドから呼び出す必要もあります。selfday()

の代わりにTimesheet.day(...)、次のようにする必要があります。

my_timesheet = Timesheet()
my_timesheet.day(...)
# Now do something with the timesheet: calculate total pay, print it out, etc.
my_timesheet.calculate_total_pay()  # Made up example
my_timesheet.print_to_screen()  # Made up example

合計給与は特定の個々のTimesheet.calculate_total_pay()タイムシートの値に依存するため、を実行しても意味がありません。インスタンスメソッドでもある必要があるため、パラメーターが必要です。実際、この場合、私は として呼び出されるべきメソッドを思い付いていません。(そのように呼び出されるメソッドは、Python では「静的メソッド」と呼ばれます)。私が思いつくメソッドの例はすべてインスタンス メソッドです (つまり、特定のタイムシートのデータにアクセスする必要があるため、インスタンスで呼び出す必要があるメソッドです)。calculate_total_pay()selfTimesheet.some_method()

少し長くなりましたが、これがクラスとインスタンスをよりよく理解するのに役立つことを願っています.

于 2013-04-28T04:04:02.463 に答える
1

workday = Timesheet.day(date, hours, rate)に変更workday = Timesheet().day(date, hours, rate)

于 2013-04-27T22:45:17.883 に答える
0

あなたが抱えている問題はTimesheet、現在のコードでインスタンスを作成していないことです。クラスのメソッドを直接呼び出すだけです。selfバインドされていないメソッドは単なる関数であるため、暗黙的に渡されるオブジェクトがないため、引数の不一致エラーが発生します。

コードを修正する方法は次のとおりです。

def add_work_day(self):
    date = input ("Enter date : ")
    hours = input ("Enter hours worked : ")
    rate = input ("Enter hourly rate : £")

    workday = Timesheet() # create Timesheet instance
    workday.day(date, hours, rate) # add a workday to it

    # presumably you'll also want to do something with `workday` here too

Timesheetさて、あなたのメソッドが入っているクラスの別の場所に作成されたインスタンスが既にあるかもしれませんself

def add_work_day(self):
    date = input ("Enter date : ")
    hours = input ("Enter hours worked : ")
    rate = input ("Enter hourly rate : £")

    self.myTimesheetInstanceCreatedSomewhereElse.day(date, hours, rate)
于 2013-04-28T02:16:52.823 に答える