0

I have a file containing classes which I want to use to store API endpoints. The reason I want to use classes, is so that I can access the endpoints by typing api.level2.resources.

Here is what the file looks like, with API as the main class and SubEntries the 'child':

class API(object):
    """
    A class for logging to stdout and/or a file. Supports color output for different log kinds.
    """

    def __init__(self):
        """
        :param log_to_file: Bool - Whether to log to a file or only to stdout (False)
        :param s: String - Log file name without extension for success logs
        :param e: String - Log file name without extension for error logs
        :param prefix: Bool - Whether to show the prefix or not
        :param timestamp: Bool - Whether to show the timestamp or not
        :param debug: Bool - Whether to show debug messages or not
        """
        self.login = '/login'
        self.logout = '/logout'
        self.sysRequest = '/sysReq'
        self.level2 = SubEntries()


class SubEntries(API):

    def __init__(self):
        super().__init__()
        self.host_info = '/info'
        self.resources = '/resources'

But, when I try and use it like this:

from src import API

api = API()
print(api.level2.resources)

I get the following error:

Traceback (most recent call last):
  File "D:/_projects/pynap/new.py", line 4, in <module>
    api = API()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
  ...
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
  File "D:\_projects\pynap\src\QAPI.py", line 24, in __init__
    super().__init__()
  File "D:\_projects\pynap\src\QAPI.py", line 18, in __init__
    self.level2 = SubEntries()
RecursionError: maximum recursion depth exceeded while calling a Python object

I am pretty sure the solution is simple, I am just not sure how to structure the class to be able to use it like I want.

3
  • Well, what do you expect? Whenever you instantiate your API object, its __init__() method is called, which then instantiates a SubEntries object whose __init__() method is called, which calls its parent __init__() method which instantiates another SubEntries instance and so on, and so on... Commented Jul 18, 2017 at 15:11
  • Possible duplicate of How to invoke the super constructor? Commented Jul 18, 2017 at 15:19
  • @zwer I am aware of this, but I don’t know how I can access the values of the sub class any other way. I only want to initialize the parent, but still load the sub class and its values into level2. Commented Jul 18, 2017 at 15:37

1 Answer 1

1

As I've said in my comment, you're quite explicitly creating a circular reference here so at one point it hits Python's recursion limit. There are a lot of ways to avoid recursion of similar-typed objects. The simplest is to have a common parent, for example:

class BaseAPI(object):
    # place here whatever you want common for all API/SubEntry objects
    pass

class API(BaseAPI):

    def __init__(self):
        self.login = '/login'
        self.logout = '/logout'
        self.sysRequest = '/sysReq'
        self.level2 = SubEntries()

class SubEntries(BaseAPI):

    def __init__(self):
        super(BaseAPI, self).__init__()
        self.host_info = '/info'
        self.resources = '/resources'

You can also override __getattr__()/__setattr__()/__delattr__() methods in your BaseAPI class and then have every property access dynamically evaluated. You can also pass an 'endpoints' dict to your BaseAPI class and have it update its self.__dict__ to get endpoints from a passed dict...

Your question lacks specificity to suggest what would be the best approach.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.