Using fields defined in constructor - Python
Question: I have a class as below that I'm using to connect to a remote SQL server
instance from a linux server python web app. I define and set cursor in the
**init** constructor and wish to use it throughout the class. How do I do
this? I come form a java background and don't understand the scope and
protection levels of Python fields.

    
    
    import pyodbc
    
    class SQLSeverConnection():
    
    
        def __init__(self, DSN, user, password, database):
            connectionString = 'DSN=%s;UID=%s;PWD=%s;DATABASE=%s;' % (DSN, user, password, database)
            connection = pyodbc.connect(connectionString)
            cursor = connection.cursor()
    
        def getColumnData(self, columnName, tableName):
    
            cursor.execute('SELECT ' columnName ' FROM ' tableName ' ORDER BY timestamp')
            data = cursor.fetchall()
    
            return data
    
        def getColumnTitles(self, tableName):
            cursor.execute('select column_name,* from information_schema.columns where table_name = 'tableName' order by ordinal_position')
    
            columns = cursor.fetchall()
    
            return columns
    
        def getTableNames(self):
            cursor.execute('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''BASE TABLE''')
    
            tables = cursor.fetchall()
    
            return tables
    


Answer: The answer is simple: Python's "methods" are really plain functions, and local
variables are plain local variables. To set / access instance attributes, you
**must** use the current instance, which is passed as first argument to the
function (and by convention named `self`):

    
    
    class SQLSeverConnection():
    
    
        def __init__(self, DSN, user, password, database):
            connectionString = 'DSN=%s;UID=%s;PWD=%s;DATABASE=%s;' % (DSN, user, password, database)
            self.connection = pyodbc.connect(connectionString)
            self.cursor = connection.cursor()
    
        def getColumnData(self, columnName, tableName):
    
            self.cursor.execute('SELECT ' columnName ' FROM ' tableName ' ORDER BY timestamp')
            data = self.cursor.fetchall()
    
            return data
    
        def getColumnTitles(self, tableName):
            self.cursor.execute('select column_name,* from information_schema.columns where table_name = 'tableName' order by ordinal_position')
    
            columns = self.cursor.fetchall()
    
            return columns
    
        def getTableNames(self):
            BASE_TABLE ='BASE_TABLE'
            self.cursor.execute('SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'')
    
            tables = self.cursor.fetchall()
    
            return tables
    

Now using a single shared cursor for all operations is brittle, you'd better
instanciate a new cursor for each operation. Also, since a cursor is an
iterable, you may want to return the cursor itself and let client code iterate
over it, it might save some memory...

    
    
    class SQLSeverConnection(object):
    
        def __init__(self, DSN, user, password, database):
            connectionString = 'DSN=%s;UID=%s;PWD=%s;DATABASE=%s;' % (DSN, user, password, database)
            self.connection = pyodbc.connect(connectionString)
    
       def getCursor(self):
           return self.connection.cursor()  
    
        def getColumnData(self, columnName, tableName):
            cursor = self.getCursor() 
            cursor.execute('SELECT ' columnName ' FROM ' tableName ' ORDER BY timestamp')
            return cursor
    
        # etc
    

Oh and yes: using `mixCased` is not pythonic, we prefer `all_lower` ;)

