Search code examples
pythonpython-3.xmysql-python

Method returning itself and a value at the same time


I am creating python wrapper on top of mysql connector. So far it was straightforward:

class DBconnector:
    def __init__(self, columns=None, values=None):
        #connect to db
        pass

    def getcolumns(self, database=None):
        columns = ("columnA1", "columnA2")
        return columns

    def getvalues(self, table=None, columns=None):
        values = ("valB1", "valB2")
        columns = columns
        return values

    def getprimary_key(self, table=None):
        table_key = "someTableKey"
        return table_key

db_conn = DBconnector()
mycolumns = db_conn.getcolumns()
myvalues = db_conn.getvalues()
mykey = db_conn.getprimary_key()
print(mycolumns, myvalues, mykey)
>>>> ('columnA1', 'columnA2') ('valB1', 'valB2') someTableKey

Now, I would like to implement chained methods like .as_list(), .as_dict() etc... That would give me an ability to get data way I need it in certain cases. For example When I ask db_conn.getvalues.asdict() I will get values and columns as a key. I could implement it like so:

class DBconnector:
    def __init__(self, columns=None, values=None):
        #connect to db
        self.columns = columns
        self.values = values

    def getvalues(self, table=None, columns=None):
        self.values = ("valB1", "valB2")
        self.columns = columns
        return self

    def __repr__(self):
        return str(self.values)

    def asdict(self):
        mydict = {}
        for idx, col in enumerate(self.columns):
            mydict[col] = self.values[idx]
        return mydict

db_conn = DBconnector()
mycolumns = db_conn.getvalues(columns=["mycolumn1", "mycolumn2"])
print(mycolumns)
print(type(mycolumns))

mydictcolumns = mycolumns.asdict()
print(mydictcolumns)

>>>> ('valB1', 'valB2')
>>>> <class '__main__.DBconnector'>
>>>> {'mycolumn1': 'valB1', 'mycolumn2': 'valB2'}

But I have few problems and a question with this approach:

Main method getvalues() would return only object that I can no longer parse directly, I would have to implement additional methods just to get values like .values() (?). Overall I am not sure how not to over complicate, make it user friendly and readable. What would be the proper approach for designing such class/module ?


Solution

  • While your intent is good ('friendly and readable'), the implementation is doubtful:

    class DBconnector:
        def __init__(self, columns=None, values=None):
            #connect to db
            self.columns = columns
            self.values = values
    
        def getvalues(self, table=None, columns=None):
            self.values = ("valB1", "valB2")
            self.columns = columns
            return self
    

    You initiate a db connector with columns and values? A connector should allow read and write something to a database, why values? What if one chooses to read something from a database. Where is a table name in your connector? The original code is very confusing, hope you can refactor it to something more readable.

    If there was just your question and no code, I'd say make a connector return the native database query result type and keep a separate function outside the class to transform this result to a different type (e.g. tuples to dicts).

    Generally, I think a very easy intro to database connectivity is https://dataset.readthedocs.io/en/latest and also https://ponyorm.com for some quick entry into ORM field.