在Python中如何从被调用模块访问调用模块名称空间?

在Python中如何从被调用模块访问调用模块名称空间?,python,sqlite,namespaces,eval,Python,Sqlite,Namespaces,Eval,我为SQLite制作了一个小小的sql渲染器/包装器。主要思想是写: execute( 'select * from talbe1 where col1={param1} and col2={param2}' ) 而不是 execute( 'select * from table1 where col1=? and col2=?', (param1,param2) ) 代码如下: import re import sqlite3 class SQLWrapper(): def __

我为SQLite制作了一个小小的sql渲染器/包装器。主要思想是写:

execute( 'select * from talbe1 where col1={param1} and col2={param2}' )
而不是

execute( 'select * from table1 where col1=? and col2=?', (param1,param2) )
代码如下:

import re
import sqlite3

class SQLWrapper():
    def __init__(self, cursor):
        self.cursor = cursor
    def execute(self, sql):
        regexp=re.compile(r'\{(.+?)\}')
        sqlline = regexp.sub('?',sql)
        statements = regexp.findall(sql)
        varlist = tuple([ eval(_statement) for _statement in statements ])
        self.cursor.execute(sqlline, varlist)
        return self
    def fetchall(self):
        return self.cursor.fetchall()

#usage example
db = sqlite3.connect(':memory:')
cursor = db.cursor()

wrap = SQLWrapper(cursor)

wrap.execute('create table t1(a,b)')
for i in range(10):
    wrap.execute('insert into t1(a,b) values({i}, {i*2})')

limit = 50
for line in wrap.execute('select * from t1 where b < {limit}').fetchall():
    print line

即,变量I在其他模块中不可见。如何克服这个问题?

这违反了大多数编程语言的正常范围规则

通常,您不希望您调用的函数(或方法)以某种方式神奇地使用您自己的变量进行操作。这意味着,只有那些变量值(!)才可访问被调用的例程,您将其显式添加为参数

当您在第一个代码中(全部在一个模块中)将带有i的for循环移动到自己的函数中时,将遇到相同的问题——我将是该函数的本地对象,并且对SQLwrapper不可见

范围规则有意地将变量的访问限制为“范围内”的变量,而不允许访问“范围外”的变量。因此,进行了一些信息隐藏,降低了复杂性

这意味着在某些情况下会有一些编写开销,但也会抑制一些危险的做法和复杂性,从而使程序更加节省

当您只打算使用SQLite(或MySQL)时,我会推荐类似的方法:

因此,您有了一个更可读、更容易理解的版本,但没有遇到的范围问题。@-前缀可以在SQLite上使用,据我所知,它也可以在MySQL中使用——但它是特定于数据库的(遗憾的是,SQL没有将其标准化)。在sqlite3模块的文档中,使用了另一个前缀“:”这也适用于SQLite,但我不知道在哪个数据库上

见:

顺便说一句,如果您想减少一点书写开销,您可以编写如下包装器:

def myExcecute(sql, **params):
   self.cursor.execute(sql, params)
因此,您可以用更少的开销(和更少的括号)调用execute:

execute( 'select * from table1 where col1=@param1 and col2=@param2', {'param1': param1, 'param2': param2} )
def myExcecute(sql, **params):
   self.cursor.execute(sql, params)
myExecute( 'select * from table1 where col1=@param1 and col2=@param2', param1=param1, param2=param2 )