我正在编辑PROSS.py以使用蛋白质结构的.cif文件。在现有的PROSS.py中,有以下函数(我相信如果它与任何类没有关联,它的名称是正确的吗?),只存在于.py文件中:
...
def unpack_pdb_line(line, ATOF=_atof, ATOI=_atoi, STRIP=string.strip):
...
...
def read_pdb(f, as_protein=0, as_rna=0, as_dna=0, all_models=0,
unpack=unpack_pdb_line, atom_build=atom_build):
我正在为命令行参数添加一个optons解析器,其中一个选项是指定除unpack_pdb_line之外使用的替代方法。所以选项解析器的相关部分是:
...
parser.add_option("--un", dest="unpack_method", default="unpack_pdb_line", type="string", help="Unpack method to use. Default is unpack_pdb_line.")
...
unpack=options.unpack_method
但是,options.unpack_method是一个字符串,我需要使用与options.unpack_method中的字符串同名的函数。如何使用getattr等将字符串转换为实际的函数名?
谢谢,
保
答案 0 :(得分:8)
通常你只需使用dict并存储(func_name, function)
对:
unpack_options = { 'unpack_pdb_line' : unpack_pdb_line,
'some_other' : some_other_function }
unpack_function = unpack_options[options.unpack_method]
答案 1 :(得分:4)
如果您想利用Python已经代表您保留的词典(& c),我建议:
def str2fun(astr):
module, _, function = astr.rpartition('.')
if module:
__import__(module)
mod = sys.modules[module]
else:
mod = sys.modules['__main__'] # or whatever's the "default module"
return getattr(mod, function)
您可能希望检查函数的签名(并捕获异常以提供更好的错误消息),例如通过inspect
,但这是一个有用的通用功能。
如果某些已知函数的完整字符串名称(包括模块/包资格)难以用这种方式表达,那么很容易添加一个快捷方式字典作为后备。
注意我们不使用__import__
的结果(当函数位于某个包内的模块中时它不起作用,因为__import__
返回包的顶级名称...只需在导入后访问sys.modules
更实用)。
答案 2 :(得分:2)
vars()["unpack_pdb_line"]()
也可以。
或
globals()或locals()也将以类似的方式工作。
>>> def a():return 1
>>>
>>> vars()["a"]
<function a at 0x009D1230>
>>>
>>> vars()["a"]()
1
>>> locals()["a"]()
1
>>> globals()["a"]()
1
干杯,
答案 3 :(得分:1)
如果您正在接受用户的输入,为了安全起见,最好是 使用手工制作的dict,它只接受一组明确定义的可接受的用户输入:
unpack_options = { 'unpack_pdb_line' : unpack_pdb_line,
'unpack_pdb_line2' : unpack_pdb_line2,
}
暂时忽略安全性,让我们顺便指出一个简单的方法 从(变量名称的字符串)到(变量名称引用的值) 是使用globals()内置字典:
unpack_function=globals()['unpack_pdb_line']
当然,只有变量unpack_pdb_line
在全局命名空间中时才会起作用。
如果您需要为模块或模块获取变量,那么 你可以使用这个功能
import sys
def str_to_obj(astr):
print('processing %s'%astr)
try:
return globals()[astr]
except KeyError:
try:
__import__(astr)
mod=sys.modules[astr]
return mod
except ImportError:
module,_,basename=astr.rpartition('.')
if module:
mod=str_to_obj(module)
return getattr(mod,basename)
else:
raise
您可以像这样使用它:
str_to_obj('scipy.stats')
# <module 'scipy.stats' from '/usr/lib/python2.6/dist-packages/scipy/stats/__init__.pyc'>
str_to_obj('scipy.stats.stats')
# <module 'scipy.stats.stats' from '/usr/lib/python2.6/dist-packages/scipy/stats/stats.pyc'>
str_to_obj('scipy.stats.stats.chisquare')
# <function chisquare at 0xa806844>
适用于嵌套包,模块,函数或(全局)变量。
答案 4 :(得分:1)
function = eval_dottedname(name if '.' in name else "%s.%s" % (__name__, name))
eval_dottedname()
:
def eval_dottedname(dottedname):
"""
>>> eval_dottedname("os.path.join") #doctest: +ELLIPSIS
<function join at 0x...>
>>> eval_dottedname("sys.exit") #doctest: +ELLIPSIS
<built-in function exit>
>>> eval_dottedname("sys") #doctest: +ELLIPSIS
<module 'sys' (built-in)>
"""
return reduce(getattr, dottedname.split(".")[1:],
__import__(dottedname.partition(".")[0]))
eval_dottedname()
是所有答案中唯一支持其中包含多个点的任意名称的答案,例如`'datetime.datetime.now'。虽然它不适用于需要导入的嵌套模块,但我甚至不记得stdlib中这样一个模块的例子。