使用numpy
时代码中有很多np.*
,例如
import numpy as np
y = np.sin(np.abs(np.linspace(0, 2*np.pi)))
这会使公式变得混乱,使它们的可读性降低。可以使用通配符导入来解决这个问题
from numpy import *
y = sin(abs(linspace(0, 2*pi)))
但是,通配符导入几乎总是一个坏主意。
我想知道是否有可能将通配符导入到仅限于公式(或数学代码块)的上下文中。这将保持可读性并将命名空间污染限制在可以更容易控制的小代码区域。我想要这样的东西:
with import_wildcard(numpy):
y2 = sin(abs(linspace(0, 2*pi)))
问题:
答案 0 :(得分:2)
class import_wildcard(object):
"""Contextmanager to temporary import a package content into the global namespace."""
def __init__(self, packagename):
self.packagename = packagename
self.package = __import__(self.packagename, globals(), locals())
self.globals_backup = {}
def __enter__(self):
_globals = globals()
for name in self.package.__dict__:
if name in _globals:
self.globals_backup[name] = _globals[name]
_globals.update(self.package.__dict__)
def __exit__(self, exc_type, exc_value, exc_tb):
_globals = globals()
for name in self.package.__dict__:
if name not in self.globals_backup:
del _globals[name]
_globals.update(self.globals_backup)
self.globals_backup.clear()
with import_wildcard('numpy'):
y = sin(abs(linspace(0, 2*pi)))
到目前为止,我没有遇到过明显的缺点。除了当然在上下文中定义的变量与numpy中的某个函数同名的变量将无法在上下文中访问。
答案 1 :(得分:1)
根据反馈,这是另一种更明确的方法。我们只是暂时将指定对象提升为全局命名空间,而不是进行临时通配符导入。
class global_context(object):
def __init__(self, *objects):
"""Return a context manager that has the given objects available in the global namespace.
You can directly pass in an object if it has a __name__, otherwise use the string name.
"""
def parse_object(obj):
if isinstance(obj, str):
ns, name = obj.split('.')
return name, getattr(globals()[ns], name)
else:
return obj.__name__, obj
self.identifiers = dict(parse_object(o) for o in objects)
self.globals_backup = {}
def __enter__(self):
_globals = globals()
for name, fn in self.identifiers.items():
if name in _globals:
self.globals_backup[name] = _globals[name]
_globals.update(self.identifiers)
def __exit__(self, exc_type, exc_value, exc_tb):
_globals = globals()
for name in self.identifiers:
if name not in self.globals_backup:
del _globals[name]
_globals.update(self.globals_backup)
self.globals_backup.clear()
用法:
import numpy as np
with global_context(np.sin, np.abs, np.linspace, 'np.pi'):
y = sin(abs(linspace(0, 2*pi)))
我将保留第一个解决方案,以便更容易讨论每种方法的优缺点,人们可以为每个解决方案投票。