Search code examples
pythonpython-2.7python-3.xserversocket

SocketServer AttributeError: Instance has no attribute 'request'


I have an issue with this mini game that i made which i am trying to add to a server.

I am trying to print a function from an instance of a Character but i'm not sure how to pass the proper function in. This is what i have:

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):
  Class Character():
    name = ""
    age = 0

  Class Human(Character):
    locationX = 0
    locationY = 0
    def help(self):
      self.request.send("Q to Quit")

  class Boy(Character, Human):
    def __init__(self, name):
      self.name = name
      age = 10

  def handle(self):
    p1 = self.Boy("Jim")

    self.request.send(":")
    command = self.request.recv(1024).strip()
    if command == "help":
      p1.help()

My error is:

    File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
      self.handle()
    File "rpg.py", line 281, in handle
      p1.help()
    File "rpg.py", line 23, in help
      self.request.send("Q to Quit")
    AttributeError: Boy instance has no attribute 'request'

Can someone explain why this is wrong?


Solution

  • You've chosen to have your classes Character &c embedded within class ThreadedTCPRequestHandler -- but embedded is very different from derived from. The embedded classes have no special access to the self of the class in which they're embedded!

    So you need to enrich e.g Character with an __init__ that takes the handler instance creating it:

      class Character():
          def __init__(self, handler):
              self.name = ""
              self.age = 0
              self.handler = handler
    

    (I've also taken the opportunity to make name and age instance variables, which makes more sense, and change indents to standard 4 characters vs the 2 you used:-).

    Subclasses must then call the base class's __init__ appropriately:

      class Boy(Character, Human):
          def __init__(self, name, handler):
              Character.__init__(self, handler)
              self.name = name
              self.age = 10
    

    and the creation of new instances must also go along:

      def handle(self):
          p1 = self.Boy("Jim", handler=self)
          # etc etc
    

    (the handler= part here is just for clarity and readability, not strictly needed for functionality:-).

    The overall architecture is now peculiar (embedded classes are rarely used in Python) but at least it will work!-)