Python ';自我';似乎占据了我的一个论点

Python ';自我';似乎占据了我的一个论点,python,oop,class,self,Python,Oop,Class,Self,我正在尝试学习python 3中的面向对象编程。我正在做一个笔记本程序的变体,我在一本书中有一个笔记本程序,但我不是在笔记本上添加注释,而是在时间表上添加天数 在原始教程中,这在主程序中: def add_note(self): memo = input("Enter a memo: ") self.notebook.new_note(memo) print("Your note has been added") 这在课堂模块(笔记本)中: 我的变体如下所示: 主要内容

我正在尝试学习python 3中的面向对象编程。我正在做一个笔记本程序的变体,我在一本书中有一个笔记本程序,但我不是在笔记本上添加注释,而是在时间表上添加天数

在原始教程中,这在主程序中:

def add_note(self):
    memo = input("Enter a memo: ")
    self.notebook.new_note(memo)
    print("Your note has been added")
这在课堂模块(笔记本)中:

我的变体如下所示:

主要内容:

模块:

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”似乎占据了我的一个输入参数

有人能告诉我这里缺少什么吗

…更新…

现在我在main中创建了Timesheet()的一个实例:

但是我的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”的预先存在的变量。我很困惑,因为这个方法在书中的示例中起作用。

更改
workday=Timesheet.day(日期、小时、费率)
workday=Timesheet().day(日期、小时、费率)
更改
workday=Timesheet.day(日期、小时、费率)
to
workday=时间表().天(日期、小时、费率)

您遇到的问题是,您没有在当前代码中创建
时间表
实例。您只是直接在类上调用一个方法。由于未绑定的方法只是函数,因此会出现参数不匹配错误,因为没有要隐式传递的
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
现在,您可能已经在方法所在的类中的其他地方创建了一个
时间表
实例。在这种情况下,您只需要引用它(通过
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)

您遇到的问题是,您没有在当前代码中创建
时间表
实例。您只是直接在类上调用一个方法。由于未绑定的方法只是函数,您将得到一个参数不匹配错误,因为没有要隐式传递的
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
现在,您可能已经在方法所在的类中的其他地方创建了一个
时间表
实例。在这种情况下,您只需要引用它(通过
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)

问题的根源在于您还不了解Python类和实例是如何工作的

类,如
时间表
,是方法(函数)和变量的集合,它们位于类的命名空间中。实例是该类的特定实例(即,此时间表,而不是所有其他存在的时间表)。每个实例都有自己的名称空间,这有点特殊:当您在实例名称空间中查找方法或变量时,如果找不到名称,则接下来将搜索类名称空间。(如果该类继承自其他类,则将按顺序搜索其祖先的名称空间,直到找到名称或没有其他名称空间可供搜索。)

现在,在类中定义的方法(函数)有一种特殊的行为,而在类之外定义的函数却没有这种行为——这就是为什么会有一个不同的术语(方法)用于类中定义的函数,以帮助提醒您此特殊行为。特殊行为是:如果对类的实例调用函数,则该实例将作为“额外”第一个参数传递给函数。(按照惯例,第一个参数被称为
self
,但如果您愿意,您没有理由不能将其称为
fhqwhgads
。您不应该这样做——这会让您的代码读起来完全混乱——但如果您愿意,您可以这样做。)为什么会有额外的第一个参数?还记得我说过实例有自己的名称空间吗?如果您想查找实例上的变量(例如,您想查找此时间表上的条目,而不是那边的其他时间表),那么您需要对实例的引用。
self
参数提供了该引用

现在,如果您在类上调用方法,而不是在实例上调用方法,则不需要额外的
self
参数,因为您显然已经有了对该类的引用:该引用是名称
Timesheet
。因此当您调用
Timesheet.day(…)
,就不会有“额外”了在其他参数之前添加了第一个参数。这是因为您不是在引用实例,而是在引用类

但是如果您调用
Timesheet().day(…)
,那么会发生两件事。首先,您正在创建
Timesheet
的一个实例(
Timesheet()
公式就是您创建实例的方式),然后您在该实例上调用
day()
方法。因此“额外”第一个参数将传递给
day()
方法,以便
day()中的代码能够访问该实例的变量

您还需要了解另一件事:变量何时属于实例,何时属于类。您可以问自己一个非常简单的问题来确定这一点:“这适用于每个时间表,还是仅适用于特定时间表?”您的
day()
方法显然需要访问特定时间表中的值(Joe的工作时间与Bob不同,工资水平也不同),因此您需要在实例中调用它,而不是在类中调用。因此,在
day()
方法中使用
self
参数是有意义的,但您也需要从方法而不是从类中调用它

因此,不是
Timesheet.day(…)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)
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