“自我”似乎在扼杀我的一个论点 [英] 'self' seems to be hogging one of my arguments

查看:95
本文介绍了“自我”似乎在扼杀我的一个论点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图学习面向对象编程在python 3.我正在做一个笔记本程序的变化,我在一本书,但不是添加笔记本笔记本我试图添加日期到时间表。 p>

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

  def add_note(self):
memo = input(输入备忘录)
self.notebook.new_note(备注)
打印(您的笔记已添加)

这是在课程模块(笔记本)中:

  def new_note(self,memo,tags =''):
'''创建一个新注释并将其添加到列表'''
self.notes .append(memo,tags =''))

我的变化形式如下: p>

main:

  def add_work_day(self):
date = input(Enter date:)
hours = input(Enter hours working:)
rate = input(输入小时费率:£)
workday = Timesheet.day日期,时间,费率)

模块:

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

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

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

它给我这个错误:

 文件C:\Python33\ timesimes_menu.py ,line 39,in add_work_day 
workday = Timesheet.day(date,hours,rate)
TypeError:day()missing 1必需的位置参数:'rate'

似乎'def day(self,date,hours,rate)'中的'self'正在占用我的一个输入参数。 p>

有人可以告诉我这里缺少什么吗?



.....更新...



现在我已经在main中创建了Timesheet()的实例:

  def add_work_day(self):
date = input(输入日期:)
小时=输入(输入工作时数:)
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,价格)
self.timesheet.append(day(date,hours,rate))

文件C:\Python33\ timesheet_menu.py,第40行,在add_work_day
workday.add_day(date,hours,rate)
文件C:\Python33\timesheet.py,第29行,在add_day
self.timesheet.append小时,费率))
NameError:未定义全局名称'day'

问题是.append(天的一部分,但我不知道如何解决它。我知道一个变量不是全局的,除非指定,但我的逻辑告诉我的方法应该是。所以它必须是.append(一天正在寻找一个名为day的pre-exisiting变量。我很困惑,因为这个方法在书中的例子中工作。

解决方案

问题的根源是你还不明白Python类和实例是如何工作的。



,例如 Timesheet 是一个方法(函数)和变量的集合,它们存在于类的命名空间中。一个实例是 类(即 时间表,而不是所有其他的时间表)每个实例都有自己的命名空间,这是特别的:当你在实例命名空间中寻找一个方法或变量时,如果没有找到该名称,那么接下来将搜索类命名空间(如果类继承自其他类,则将依次搜索其祖先的命名空间,直到找到名称或没有更多命名空间)



现在,在类中定义的方法(函数)具有特殊的行为,在之外有 - 这就是为什么不同的术语(方法)用于类中定义的函数,以帮助提醒您这种特殊的行为。特殊的行为是:如果函数在类的实例上被调用,那么该实例将作为额外第一个参数传递给函数。 (按照惯例,第一个参数被调用 self ,但没有理由你不能调用 fhqwhgads 你不应该 - 它只是让你的代码完全混乱阅读 - 但你可以,如果你想)。为什么额外的第一个参数?好吧,记得我说的实例有自己的命名空间?如果您想在实例上查找变量(例如,您要查找时间表上的条目,而不是那里的其他时间表),那么您需要对实例的引用。 self 参数提供该引用。



现在,如果你调用 em>,而不是在实例上,不需要额外的 self 参数,因为你显然已经有一个类的引用:该引用是 Timesheet 的名称。因此,当你执行 Timesheet.day(...)时,在你的其他参数之前不会有额外的第一个参数。这是因为你没有引用一个实例,你引用了一个类。



但是如果你调用 Timesheet()。day 。),那么就会发生两件事。首先,您要创建 Timesheet 实例 Timesheet()如何创建实例),然后调用该实例上的 day()方法。因此,extra第一个参数将被传递到 day()方法,使得 day()将能够访问该实例的变量。



另一件你需要理解的事情:当变量属于一个实例,并且它们属于一个类。有一个非常简单的问题,您可以问自己确定这一点:这适用于个时间表,还是只适用于 时间表?您的 day()方法显然需要从特定时间表访问值(Joe与Bob工作时间不同,但工资不同),因此您需要在实例上调用它,而不是在类上。所以在 day()方法中有一个 self 参数是有意义的,但是你还需要从一个方法,而不是类。



因此,不要使用 Timesheet.day(...) like:

  my_timesheet = Timesheet()
my_timesheet.day(...)
#时间表:计算总工资,打印出来等等。
my_timesheet.calculate_total_pay()#make up example
my_timesheet.print_to_screen()#Make up example

Timesheet.calculate_total_pay()取决于特定的个别时间表中的值。因此, calculate_total_pay()也应该是一个实例方法,因此应该有一个 self 参数。实际上,在这种情况下,我没有提出任何应该调用 Timesheet.some_method()的方法。 (Python中称为静态方法的方法,BTW)。我可以想出的每一个示例方法是一个实例方法(即,应该在实例上调用的方法,因为它需要从特定时间表访问数据)。



有点长,但我希望这有助于你更好地了解类和实例。


I am trying to learn object orientated programming in python 3. I am making a variation of a notebook program that I have in a book but instead of adding notes to a notebook I am trying to add days to a timesheet.

In the original tutorial, this is in the main program:

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

and this is in the class module (notebook):

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

My variation looks like this:

main:

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)

module:

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

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

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

It is giving me this error:

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'

It seems like the 'self' in 'def day(self, date, hours, rate)' is hogging one of my input arguments.

Can someone tell me what I am missing here?

.....Update.....

So now I have created an instance of Timesheet() in main:

    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) 

But I am getting a new error from my Timesheet() method '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

I understand that the problem is the .append(day part but I can't figure out how to fix it. I know a variable isn't global unless specified but my logic tells me that the method should be. So it must be that the .append(day is looking for a pre-exisiting variable called 'day'. I'm confused because this method worked in the example from the book.

解决方案

The root of your problem is that you don't yet understand how Python classes and instances work.

A class, like Timesheet, is a collection of methods (functions) and variables, which live in the class's namespace. An instance is a specific instance of the class (i.e., this timesheet, as opposed to all the other timesheets that exist). Each instance has its very own namespace, which is slightly special: when you look for a method or variable in an instance namespace, if the name is not found, the class namespace will be searched next. (And if the class inherits from other classes, the namespaces of its ancestors will be searched, in order, until either the name is found or there are no more namespaces left to search.)

Now, methods (functions) defined in classes have a special behavior, which functions defined outside of classes don't have -- this is why a different term (methods) is used for functions defined in classes, to help remind you of this special behavior. The special behavior is this: if the function is being called on an instance of the class, then that instance will get passed as an "extra" first parameter to the function. (By convention, that first parameter is called self, but there's no reason you couldn't call it fhqwhgads if you wanted to. You shouldn't -- it would just make your code utterly confusing to read -- but you could if you wanted to.) Why that extra first paremeter? Well, remember how I said that instances have their own namespace? If you want to look up variables on the instance (e.g., you want to look up the entries on this timesheet, not that other timesheet over there), then you need a reference to the instance. The self parameter provides that reference.

Now, if you call the methods on the class, as opposed to on an instance, there's no need for that extra self parameter, because you clearly already have a reference to the class: that reference is the name Timesheet. So when you do Timesheet.day(...), there will be no "extra" first parameter added before your other parameters. That's because you're not referencing an instance, you're referencing a class.

But if you call Timesheet().day(...), then two things are happening. First, you're creating an instance of Timesheet (the Timesheet() formulation is how you create an instance), and then you're calling the day() method on that instance. So the "extra" first parameter will be passed to your day() method so that your code inside day() will be able to access that instance's variables.

One other thing you'll need to understand: when variables belong on an instance, and when they belong on a class. There's a very simple question you can ask yourself to determine this: "does this apply to every timesheet, or only to specific timesheets?" Your day() method clearly needs to access values from specific timesheets (Joe worked different hours than Bob, at a different rate of pay), so you need to call it on instances, not on the class. So having a self parameter in your day() method makes sense, but you also need to call it from a method, not from the class.

So instead of Timesheet.day(...), you should do something like:

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

It would make no sense to do Timesheet.calculate_total_pay(), because the total pay depends on the values in specific, individual timesheets. So calculate_total_pay() should also be an instance method, and should therefore have a self parameter. Actually, in this case I'm not coming up with any methods that should be called as Timesheet.some_method(). (Methods called like that are called "static methods" in Python, BTW). Every single example method I can come up with is an instance method (i.e., a method that should be called on an instance, because it would need to access data from that specific timesheet).

A bit long-winded, but I hope this helps you understand classes and instances better.

这篇关于“自我”似乎在扼杀我的一个论点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆