2

I'm trying to create a class for interacting with a MySQL Database. This class will connect to the database storing the connection object and cursor. Allowing for multiple actions without reconnecting every time. Once you're done with it, the cursor and connection need to be closed. So I've implemented it as a context manager and it works great.

I need the support to be able to do multiple actions without reopening the connection each time, but most of the time I am only running one Query/command. So I end up having to write the below code to run a single query.

with MySQLConnector() as connector:
    connector.RunQuery(QUERY)

I thought it would be nice to be able to run single line commands like this

MySQLConnector().RunQuery(QUERY)

but this leaves the connection open.

I then thought this implementation would allow me to do single and multiple actions all nicely context managed.

class MySQLConnector():
    @staticmethod
    def RunQuery(query):
        with MySQLConnector() as connector:
            connector.RunQuery(query)

    def RunQuery(self, query):
        self.cursor.execute(query)
        self.connection.commit()

# Single Actions
MySQLConnector.RunQuery(QUERY)

# Mulitple Actions
with MySQLConnector() as connector:
    connector.RunQuery(QUERY_1)
    connector.RunQuery(QUERY_2)

However, the method function seems to override the static method and only one way will work at a time. I know I could just have two separately named functions but I was wondering if there was a better/more pythonic way to implement this?

J Browne
  • 23
  • 3
  • 2
    Does this answer your question? [Python: Regular method and static method with same name](https://stackoverflow.com/questions/20533349/python-regular-method-and-static-method-with-same-name) – Michael M. Jan 27 '23 at 03:32
  • An uglier way to do it might be `def RunQuery(self_or_query, query=None)` and then use `if isinstance(self_or_query, MySQLConnector)` to determine which code to run. – Fractalism Jan 27 '23 at 03:45
  • 1
    @MichaelM. That is a very functional way to do this. My only comments on it is when I call `connector.RunQuery` inside the static function it isn't recognized. – J Browne Jan 27 '23 at 03:50
  • 1
    @Fractalism. Though uglier, it probably would be easier to understand than the fancy redefining of the method in `__init__` – J Browne Jan 27 '23 at 03:51
  • 1
    @MichaelM. I'm correcting myself from earlier instead of just not being recognized, it actually can't call RunQuery from anywhere inside the class. Instead you have to opt to calling _instance_RunQuery – J Browne Jan 27 '23 at 03:57
  • 1
    @MichaelM. Once again correcting myself. The solution in [Python: Regular method and static method with same name](https://stackoverflow.com/questions/20533349/python-regular-method-and-static-method-with-same-name) was a perfect fit. I just had a syntax error. You can call RunQuery from anywhere in the class without needing to call its _instance counterpart – J Browne Jan 27 '23 at 04:12

1 Answers1

1

As this answer points out, you can use some __init__ trickery to redefine the method if it is being used as non-static (as __init__ will not run for static methods). Change the non-static RunQuery to something like _instance_RunQuery, then set self.RunQuery = self._instance_RunQuery. Like this:

class A:
    def __init__(self, val):
        self.add = self._instance_add
        self.val = val

    @staticmethod
    def add(a, b):
        obj = A(a)
        return obj.add(b)

    def _instance_add(self, b):
        return self.val + b


ten = A(10)
print(ten.add(5))

print(A.add(10, 5))
Michael M.
  • 10,486
  • 9
  • 18
  • 34
  • Out of curiosity do you think this could be possible to do with decorators? – J Browne Jan 27 '23 at 04:27
  • 1
    @JBrowne I just tried to create an example using decorators, but I couldn't find a way. I don't think it's possible because I don't believe there's any way to get `self` from the decorator. – Michael M. Jan 27 '23 at 04:39