“超级”对象的描述符“__init__”需要参数

Posted

技术标签:

【中文标题】“超级”对象的描述符“__init__”需要参数【英文标题】:descriptor '__init__' of 'super' object needs argument 【发布时间】:2014-07-15 19:22:38 【问题描述】:

我正在尝试用 Python 制作一个面向对象的基于文本的游戏,并尝试实现我的第一个属性和装饰器。使用'Python 3 Object Oriented Programming' 中的第 5 章,我尝试使用讨论的示例和概念来获取以下代码,以便在实例化时设置游戏对象的 'current_room' 属性:

class Room(object):
    ''' An area of the game's map.'''
    def __init__(self):
        print("Accessing the Room __init__ method.")


class FirstRoom(Room):
    ''' Just some room.'''
    def __init__(self):
        print("Accessing the FirstRoom __init__ method.")
        super.__init__()


class SecondRoom(Room):
    ''' Just some other room.'''
    def __init__(self):
        print("Accessing the SecondRoom __init__ method.")
        super.__init__()


class Game(object):
    ''' Creates a new game.'''
    current_room = None # Class-level definition of this property.

    def __init__(self):
        print("Created a new Game object.")
        self.current_room = FirstRoom()

    @property
    def current_room(self):
        ''' Returns the current position of the actor.'''
        print("Getting the _current_room attribute for the Game object.")
        return self._current_room

    @current_room.setter   
    def set_room(self, new_room):
        ''' Sets the current_room property of the Game object.'''
        print("Setting the _current_room attribute for the Game object.")
        self._current_room = new_room

但是,当我运行此代码时,我得到以下输出:

>>> g = Game()
Created a new Game object.
Accessing the FirstRoom __init__ method.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/drew/Desktop/test.py", line 27, in __init__
    self.current_room = FirstRoom()
  File "/home/drew/Desktop/test.py", line 11, in __init__
    super.__init__()
TypeError: descriptor '__init__' of 'super' object needs an argument

我的代码中缺少什么以使此语法正常工作?我需要为我的“current_room”属性显式定义一个描述符吗? [这本书没有提到任何关于描述符的内容,至少不像你在这里看到的那样:Python Descriptors Demystified。]

【问题讨论】:

您实际上需要致电 super How to call Base Class's __init__ method from the child class?的可能重复 看起来像语法 super().__init__() 并将 self.current_room = FirstRoom() 更改为 self._current_room = FirstRoom() 修复了下一个错误。谢谢! @RSahu 我不认为这个问题是重复的(至少是那个问题)。事实上,OP 的问题不是调用super 而您链接的问题确实 调用super 并且产生的错误完全不同。 【参考方案1】:

super 错误实际上是在您调用 super 之前将 print 打印出来,以下代码可以正常工作:

class Room(object):
    ''' An area of the game's map.'''
    def __init__(self):
        print("Accessing the Room __init__ method.")


class FirstRoom(Room):
    ''' Just some room.'''

    def __init__(self):
        super().__init__()
        print("Accessing the FirstRoom __init__ method.")



class SecondRoom(Room):
    ''' Just some other room.'''

    def __init__(self):
        super().__init__()
        print("Accessing the SecondRoom __init__ method.")

您需要了解@property 等的工作原理。

Property python docs

从文档中,确保为附加函数提供与原始属性相同的名称

class Game(object):
    ''' Creates a new game.'''
    current_room = None  # Class-level definition of this property.

def __init__(self):
    print("Created a new Game object.")
    self._current_room = FirstRoom()

@property
def current_room(self, room): 
    ''' Returns the current position of the actor.'''
    print("Getting the _current_room attribute for the Game object.")
    return self._current_room


@current_room.setter # same function name as the property.
def current_room(self, new_room):# same name  as the property
    ''' Sets the current_room property of the Game object.'''
    print("Setting the _current_room attribute for the Game object.")
    self._current_room=new_room  

【讨论】:

是的,使用 Python 3.4.0。 不用担心。看看文档,有几个很好的例子来说明 @property 等是如何工作的。【参考方案2】:

这里是工作代码:

class Room(object):
    ''' An area of the game's map.'''
    def __init__(self):
        print("Accessing the Room __init__ method.")


class FirstRoom(Room):
    ''' Just some room.'''
    def __init__(self):
        print("Accessing the FirstRoom __init__ method.")
        #super.__init__()
        super(FirstRoom, self).__init__()


class SecondRoom(Room):
    ''' Just some other room.'''
    def __init__(self):
        print("Accessing the SecondRoom __init__ method.")
        super(SecondRoom, self).__init__()
        #super.__init__()


class Game(object):
    ''' Creates a new game.'''
    _current_room = None # Class-level definition of this property.

    def __init__(self):
        print("Created a new Game object.")
        self._current_room = FirstRoom()

    @property
    def current_room(self):
        ''' Returns the current position of the actor.'''
        print("Getting the _current_room attribute for the Game object.")
        return self._current_room

    @current_room.setter   
    def set_room(self, new_room):
        ''' Sets the current_room property of the Game object.'''
        print("Setting the _current_room attribute for the Game object.")
        self._current_room = new_room

当运行时:

>>> g = Game()
Created a new Game object.
Accessing the FirstRoom __init__ method.
Accessing the Room __init__ method.
>>> 

希望对您有所帮助。

【讨论】:

【参考方案3】:

使用super().__init__() 代替super.__init__()

【讨论】:

谢谢你,亲爱的

以上是关于“超级”对象的描述符“__init__”需要参数的主要内容,如果未能解决你的问题,请参考以下文章

当父级不从对象继承时,Python 2.x 超级 __init__ 继承不起作用

描述符简单应用示例

描述符

为啥 Counter 的 __init__ 方法称为描述符?

7_27描述符 18min

成员修饰符