在Python模块中隐藏中间计算
我在Jupyter笔记本中有一个Python文件,在Python模块中隐藏中间计算,python,namespaces,ipython,jupyter-notebook,Python,Namespaces,Ipython,Jupyter Notebook,我在Jupyter笔记本中有一个Python文件,src/data.py,用于读取数据文件并提供一些输出 import numpy as np import pandas as pd sha256_perf = ( pd.read_csv('data/hashbench-output.txt', sep='\t', na_filter=False) .query('Algorithm == "SHA256"') ) mean_throughput = sha256_p
src/data.py
,用于读取数据文件并提供一些输出
import numpy as np
import pandas as pd
sha256_perf = (
pd.read_csv('data/hashbench-output.txt', sep='\t', na_filter=False)
.query('Algorithm == "SHA256"')
)
mean_throughput = sha256_perf['Throughput (MiB/s)'].mean()
variance = sha256_perf['Error (± MiB/s)'] ** 2
total_variance = variance.sum()
row_count = sha256_perf.shape[0]
variance_of_mean = total_variance / (row_count ** 2)
error_of_mean = variance_of_mean ** 0.5
sha256_summary = pd.DataFrame(data=[[mean_throughput, error_of_mean]])
sha256_summary.columns = ['Mean Throughput (MiB/s)', 'Error (± MiB/s)']
其中,我关心的唯一变量是输出表--sha256_perf
和sha256_summary
。但是,Python无法知道这一点,因此,如果我dir()
module,我会得到所有信息:
>>> import src.data as data
>>> dir(data)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'assumptions', 'error_of_mean',
'mean_throughput', 'np', 'pd', 'prd_scratch_2018', 'row_count', 'sha256_perf',
'sha256_summary', 'total_variance', 'util', 'variance', 'variance_of_mean']
如果这是Ruby或Scala,我可以在块中初始化sha256\u summary
,类似于:
sha256\u summary=begin
平均吞吐量=sha256性能[‘吞吐量(MiB/s)].mean()
# ... 等
df.columns=[“平均吞吐量(MiB/s)”,“错误(±MiB/s)”]
df
结束
即使在Java(8+),我也可以与供应商和lambda一起破解一些东西
但据我所知,Python没有匿名块或多行lambda。到目前为止,我能想到的最好办法是将所有内容都放在函数中:
def create_summary():
平均吞吐量=sha256性能[‘吞吐量(MiB/s)].mean()
# ... 等
sha256_summary.columns=[“平均吞吐量(MiB/s)”,错误(±MiB/s)]
返回shau摘要
sha256_summary=创建_summary()
但这仍然会导出create\u summary
符号,我宁愿避免:
>>> dir(data)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'assumptions', 'create_summary',
'np', 'pd', 'prd_scratch_2018', 'sha256_perf', 'sha256_summary', 'util']
避免污染全局名称空间的python方法是什么?您没有污染全局名称空间,因为您不关心的变量仍然在
数据名称空间中,也就是说,它们是数据模块的属性
此外,您不能仅隐藏模块属性:如果模块中定义了create\u summary
,则import data
将带进data
及其create\u summary
属性。
但是,您可以通过在data.py
末尾调用del create\u summary
来删除它。
这样,它就不会出现在dir(data)
中
下面是一个简短的例子:
# data.py
module_level_attribute = None
def init():
global module_level_attribute
module_level_attribute = 2
init()
del init
然后,module\u level\u属性
将出现在dir(data)
中,而不是init
:
>>> import data
>>> dir(data)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
'__name__', '__package__', '__spec__', 'module_level_attribute']
不过,使用del
语句并不是很令人满意
我更喜欢的方法是在函数中进行所有处理,只提供感兴趣的变量作为模块级属性,就像您所做的那样。
这没关系,因为它实际上不会污染全局名称空间。
更进一步说,您可以用一个前导下划线来命名该初始化函数,以指示它是“private”,这将在help
函数中隐藏它,尽管它仍然会出现在dir(data)
中
但是,如果您真的只想导入您需要的内容,那么您应该使用来自的。。。导入
语法。
这一次,导入的变量将被带入全局名称空间,因此您将失去data.sha256_perf
的明确性。
另一方面,您不会从数据模块获得任何其他内容。很好,但我想指出在模块中定义“有意义”名称的其他方法,而不是事后删除内容
第一个选项是在模块中定义\uuuuuuuuuuuuuuuuuuuuuuuuuuu
<代码>\uuuuuuuuuuuuuuuuuuuuuuu
是一系列字符串,它们是模块接口的一部分;如果您模块的用户从modulename import*
中执行,并且定义了\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,则他们只会在\u。因此,在您的情况下,您只需添加:
__all__ = ['sha256_perf', 'sha256_summary']
靠近模块顶部(位置不重要,但按照惯例,它位于顶部附近,通常在导入之后)。许多自省工具也使用此信息来限制输出中包含模块的哪些部分(例如带有\uuuu all\uuuu
的模块上的帮助(modulename)
排除了\uu all\uuu>中未包含的类和函数)
或者,您可以避免使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;如果未定义\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。因此,如果除了您关心的两个名称之外,所有名称都带有下划线前缀(包括导入的模块名称,例如,import numpy as\u np
,import pandas as\u pd
),那么在使用modulename import*
中的时,它们将被忽略,并且通常在help()
输出等中被忽略
不,它不会更改dir所看到的名称集(虽然制表符完成功能经常会忽略以下划线开头的名称),但这是声明被视为公共API一部分的名称的正式方式。如果您想要块初始化行为,只需重新使用变量名作为函数名
def sha256_summary():
mean_throughput = sha256_perf['Throughput (MiB/s)'].mean()
# ... etc. ...
sha256_summary.columns = ['Mean Throughput (MiB/s)', 'Error (± MiB/s)']
return sha256_summary
sha256_summary = sha256_summary()
是的,这在Python中是允许的。函数只是另一种值。这将在模块的全局中设置名为sha256_summary
的函数,然后下面的赋值语句将用其返回值覆盖该名称
Python的装饰程序一直使用这种模式。它们通常返回一个包装函数替换,但这实际上不是必需的。装饰器可以返回任何值,该值替换本地范围内函数的名称。因此,我们可以作为装饰器实现上述模式
def begin(f):
return f()
那么如果你像这样装饰这个功能
@begin
def sha256_summary():
mean_throughput = sha256_perf['Throughput (MiB/s)'].mean()
# ... etc. ...
sha256_summary.columns = ['Mean Throughput (MiB/s)', 'Error (± MiB/s)']
return sha256_summary
在sha256_summary
中再次获得返回值,而不重复名称。当然,begin
现在是模块中的全局变量。如果必须,请稍后删除它,但在Python中,模块包含的内容超过其预期的导出内容是正常的。在函数中执行所有操作,调用该函数,然后删除该函数。申报任何你想保留的东西
def _private():
import numpy as np
import pandas as pd
global sha256_perf
sha256_perf = (
pd.read_csv('data/hashbench-output.txt', sep='\t', na_filter=False)
.query('Algorithm == "SHA256"')
)
mean_throughput = sha256_perf['Throughput (MiB/s)'].mean()
variance = sha256_perf['Error (± MiB/s)'] ** 2
total_variance = variance.sum()
row_count = sha256_perf.shape[0]
variance_of_mean = total_variance / (row_count ** 2)
error_of_mean = variance_of_mean ** 0.5
global sha_256_summary
sha256_summary = pd.DataFrame(data=[[mean_throughput, error_of_mean]])
sha256_summary.columns = ['Mean Throughput (MiB/s)', 'Error (± MiB/s)']
_private()
del _private
from .data import sha256_perf, sha256_summary