gpt4 book ai didi

python - 如何从 Python 中的被调用模块访问调用模块命名空间?

转载 作者:行者123 更新时间:2023-12-04 16:57:43 25 4
gpt4 key购买 nike

我为 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

它有效,但是当我移动类(class)时 SQLWrapper到一个单独的模块(文件 sqlwrap.py)并导入它,程序崩溃:
Traceback (most recent call last):
File "c:\py\module1.py", line 15, in <module>
wrap.execute('insert into t1(a,b) values({i}, {i*2})')
File "c:\py\sqlwrap.py", line 10, in execute
varlist = tuple([ eval(_statement) for _statement in statements ])
File "<string>", line 1, in <module>
NameError: name 'i' is not defined

IE。变量 i 在其他模块中不可见。如何克服这一点?

最佳答案

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

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

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

范围规则有意将变量的访问限制为“范围内”的变量,并且不允许访问“范围外”的事物。这样就完成了一些信息隐藏并降低了复杂性。

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

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

execute( 'select * from table1 where col1=@param1 and col2=@param2', {'param1': param1, 'param2': param2} )

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

见: sqlite3.Cursor.execute documentation

顺便说一句,如果你想稍微减少你的写作开销,你可以写一些这样的包装器:
def myExcecute(sql, **params):
self.cursor.execute(sql, params)

因此,您可以以更少的开销(和更少的括号)调用 execute:
myExecute( 'select * from table1 where col1=@param1 and col2=@param2', param1=param1, param2=param2 )

关于python - 如何从 Python 中的被调用模块访问调用模块命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26414878/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com