级别:初学者
我正在做我的面向对象编程的第一步。代码的目的是展示方法是如何在链中向上传递的。因此,当我调用UG.say(person, 'but i like')时,say方法被指示调用类MITPerson。鉴于MITPerson不包含say方法,它将把它向上传递给Person类。我认为代码没有问题,因为它是讲座的一部分(参见下面的源码)。我认为是我在运行代码时遗漏了定义某些东西。但不确定是什么。我认为作为第一个参数的错误消息寻找的UG instance引用了self,但原则上不需要提供,对吗?有什么提示吗?
class Person(object):
def __init__(self, family_name, first_name):
self.family_name = family_name
self.first_name = first_name
def familyName(self):
return self.family_name
def firstName(self):
return self.first_name
def say(self,toWhom,something):
return self.first_name + ' ' + self.family_name + ' says to ' + toWhom.firstName() + ' ' + toWhom.familyName() + ': ' + something
class MITPerson(Person):
def __init__(self, familyName, firstName):
Person.__init__(self, familyName, firstName)
class UG(MITPerson):
def __init__(self, familyName, firstName):
MITPerson.__init__(self, familyName, firstName)
self.year = None
def say(self,toWhom,something):
return MITPerson.say(self,toWhom,'Excuse me, but ' + something)
>>> person = Person('Jon', 'Doe')
>>> person_mit = MITPerson('Quin', 'Eil')
>>> ug = UG('Dylan', 'Bob')
>>> UG.say(person, 'but i like')
UG.say(person, 'bla')
**EDIT (for completeness)**: it should say UG.say(person, 'but i like') #the 'bla' creeped in from a previous test
TypeError: unbound method say() must be called with UG instance as first argument (got Person instance instead)来源:麻省理工学院OpenCourseWare http://ocw.mit.edu计算机科学与编程入门2008秋季
发布于 2010-09-26 22:35:30
您正在调用类而不是实例。
>>> ug = UG('Dylan', 'Bob')
>>> UG.say(person, 'but i like')
UG.say(person, 'bla')改为调用实例
>>> ug = UG('Dylan', 'Bob')
>>> ug.say(person, 'but i like')发布于 2010-09-26 23:09:19
答案很好,但我认为有一个附注是很重要的。获取代码片段(在MITPerson类中):
def __init__(self, familyName, firstName):
Person.__init__(self, familyName, firstName)这段代码完全没有用,而且是多余的。当子类不需要在其超类的方法实现中重写任何内容时,子类看起来像是“重写”该方法是完全没有用的……然后将所有工作委托给超类,而不做任何更改。
完全没有目的,永远不会有任何影响的代码(除了略微降低整个系统的速度),因此可以不受任何伤害地删除的代码应该被删除:为什么要把它放在那里?!程序中存在的任何代码都不可避免地会损害程序的质量:这种无用的“镇流器”稀释了有用的、有效的代码,使程序更难阅读、维护和调试,等等。
大多数人似乎在大多数情况下都直观地理解了这一点(因此,您看不到许多“伪覆盖”大多数方法的代码,但在方法体中,它们只是指向超类实现),除了__init__ --由于某种原因,许多人似乎有一个心理盲点,只是看不到与其他方法完全相同的规则。这种盲点可能来自于熟悉其他完全不同的语言,在这些语言中,规则不适用于类的构造函数,再加上将__init__视为实际上不是的构造函数(它是一个初始化器)的误解。
所以,总而言之:一个子类应该定义__init__当且仅当它需要在超类自己的初始化器之前或之后,或者在它自己的初始化器之前和之后做一些其他的事情(很少它可能想要做一些而不是,即而不是委托给超类初始化器,但这几乎不是一个好的做法)。如果子类的__init__主体的只是了一个对超类的__init__的调用,并以相同的顺序使用完全相同的参数,那么从代码中删除子类的__init__ (就像您对任何其他类似冗余的方法所做的那样)。
发布于 2010-09-26 22:31:20
变化
UG.say(person, 'but i like')至
ug.say(person, 'but i like')UG.say返回未绑定的方法say。“未绑定”意味着不会自动填充say的第一个参数。未绑定的方法say有3个参数,第一个参数必须是UG的实例。相反,UG.say(person, 'but i like')将Person的一个实例作为第一个参数发送。这解释了Python给出的错误消息。
相反,ug.say返回绑定的方法say。"Bound“意味着要说的第一个参数将是ug。绑定方法有两个参数:toWhom和something。因此,ug.say(person, 'but i like')的工作方式与预期一致。
unbound method has been removed from Python3的概念。相反,UG.say只返回一个函数,该函数(仍然)需要3个参数。唯一的区别是不再对第一个参数进行类型检查。但是,您仍然会得到一个错误,只是一个不同的错误:
TypeError: say() takes exactly 3 positional arguments (2 given)PS。当开始学习Python时,我想我只是尝试接受UG.say返回一个未绑定的方法(期望3个参数),而ug.say是调用一个方法(期望2个参数)的正常方式。稍后,要真正了解attribute lookup如何实现这种行为差异(同时保持相同的限定名语法),您需要研究descriptors和Python的规则。
https://stackoverflow.com/questions/3798194
复制相似问题