Python 为什么我的代码在函数形式上慢得多?

Python 为什么我的代码在函数形式上慢得多?,python,python-2.7,performance,function,Python,Python 2.7,Performance,Function,我不久前写了一段代码,它使用文本文件中的数据处理光谱并对其进行计算。我从一个代码开始,它一行一行地执行所有操作,没有任何函数,尽管很长,但它在2.11秒内完成运行(根据%%timeit)。下面是原始代码,标记为 但是,我希望将代码放在函数中,以便将来在不同的模型中更易于阅读和使用。尽管我使用的步骤与以前相同(但这次是在我的函数中),但速度要慢得多。此代码也在下面。现在,我必须等待大约15-20分钟才能获得相同的输出。为什么它会慢得多,有没有什么方法可以让它大大加快,但仍然使用函数 原始代码: i

我不久前写了一段代码,它使用文本文件中的数据处理光谱并对其进行计算。我从一个代码开始,它一行一行地执行所有操作,没有任何函数,尽管很长,但它在2.11秒内完成运行(根据
%%timeit
)。下面是原始代码,标记为

但是,我希望将代码放在函数中,以便将来在不同的模型中更易于阅读和使用。尽管我使用的步骤与以前相同(但这次是在我的函数中),但速度要慢得多。此代码也在下面。现在,我必须等待大约15-20分钟才能获得相同的输出。为什么它会慢得多,有没有什么方法可以让它大大加快,但仍然使用函数

原始代码:

import re
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate
filename = 'bpass_spectra.txt'
extinctionfile = 'ExtinctionLawPoints.txt' # from R_V = 4.0
pointslist = []
datalist = []
speclist = []

# Constants
Msun = 1.98892e30 # solar mass [kg]
h = 4.1357e-15 # Planck's constant [eV s]
c = float(3e8) # speed of light [m/s]

# Read spectra file
f = open(filename, 'r')
rawspectra = f.readlines()
met = re.findall('Z\s=\s(\d*\.\d+)', rawspectra[0])
del rawspectra[0]
for i in range(len(rawspectra)):
    newlist = rawspectra[i].split(' ')
    datalist.append(newlist)

# Read extinction curve data file
rawpoints = open(extinctionfile, 'r').readlines()
for i in range(len(rawpoints)):
    newlst = re.split('(?!\S)\s(?=\S)|(?!\S)\s+(?=\S)', rawpoints[i])
    pointslist.append(newlst)
pointslist = pointslist[3:]
lambdalist = [float(item[0]) for item in pointslist]
k_abslist = [float(item[4]) for item in pointslist]
xvallist = [(c*h)/(lamb*1e-6) for lamb in lambdalist]
k_interp = scipy.interpolate.interp1d(xvallist, k_abslist)

# Create new lists
Elist = [float(item[0]) for item in datalist]
speclambdalist = [h*c*1e9/E for E in Elist]
z1list = [float(item[1]) for item in datalist]
speclist.extend(z1list)
met = met[0]
klist = [None]*len(speclist)
Loutlist = [None]*len(speclist)
Tlist = [None]*len(speclist)

# Define parameters
b = 2.0
R = 1.0
z = 1.0
Mgas = 1.0 # mass of gas, input
Mhalo = 2e41 # mass of dark matter halo, known
if float(met) > 0.0052:
    DGRlist = [50.0*np.exp(-2.21)*float(met)]*len(speclist)
elif float(met) <= 0.0052:
    DGRlist = [((50.0*float(met))**3.15)*np.exp(-0.96)]*len(speclist)
for i in range(len(speclist)):
    if float(Elist[i]) <= 4.1357e-3: # frequencies <= 10^12 Hz
        klist[i] = 0.1*(float(Elist[i])/(1000.0*h))**b # extinction law [cm^2/g]
    elif float(Elist[i]) > 4.1357e-3: # frequencies > 10^12 Hz
        klist[i] = k_interp(Elist[i]) # interpolated function's value at Elist[i]
Mdustlist = [Mgas*DGR for DGR in DGRlist] # dust mass
Rhalo = 0.784*(0.27**2.0)*(0.7**(-2.0/3.0))*float(10.0/(1.0+z))*((Mhalo/(1e8*Msun))**(1.0/3.0))
Rdust = 0.018*Rhalo # [kpc]

for i in range(len(speclist)):
    Tlist[i] = 3*Mdustlist[i]*klist[i]/(4*np.pi*Rdust)

Linlist = [float(spectra)*R for spectra in speclist]

# Outgoing luminosity as function of wavelength
for i in range(len(Linlist)):
    Loutlist[i] = Linlist[i]*np.exp(-Tlist[i])

# Test the calculation
print "LIN ELEMENTS 0 AND 1000:", Linlist[0], Linlist[1000]
print "LOUT ELEMENTS 0 AND 1000:", Loutlist[0], Loutlist[1000]
重新导入
将matplotlib.pyplot作为plt导入
将numpy作为np导入
导入scipy.interpolate
文件名='bpass\u spectra.txt'
灭绝文件='extractionlawpoints.txt'#来自R_V=4.0
pointslist=[]
数据列表=[]
speclist=[]
#常数
Msun=1.98892e30#太阳质量[kg]
h=4.1357e-15#普朗克常数[eV s]
c=浮子(3e8)#光速[m/s]
#读取光谱文件
f=打开(文件名“r”)
rawspectra=f.readlines()
met=re.findall('Z\s=\s(\d*\.\d+),rawspectra[0])
del rawspectra[0]
对于范围内的i(len(RawSpectrum)):
newlist=rawspectra[i]。拆分(“”)
追加(newlist)
#读取消光曲线数据文件
rawpoints=open(灭绝文件'r')。readlines()
对于范围内的i(len(原始点)):
newlst=re.split('(?!\S)\S(?=\S)|(?!\S)\S+(?=\S'),原始点[i])
pointslist.append(newlst)
pointslist=pointslist[3:]
lambdalist=[pointslist中的项的浮点值(项[0])]
k_abslist=[pointslist中项目的浮动(项目[4])]
xvallist=[(c*h)/(lamb*1e-6)表示lambdalist中的lamb]
k_interp=scipy.interpolate.interp1d(xvallist,k_abslist)
#创建新列表
Elist=[datalist中项目的浮动(项目[0])]
speclambdalist=[h*c*1e9/E表示Elist中的E]
z1list=[数据列表中项目的浮动(项目[1])]
speclist.extend(z1list)
met=met[0]
klist=[None]*len(speclist)
Loutlist=[None]*len(规格列表)
Tlist=[None]*len(speclist)
#定义参数
b=2.0
R=1.0
z=1.0
Mgas=1.0#气体质量,输入
Mhalo=2e41#暗物质晕的质量,已知
如果浮动(met)>0.0052:
DGRlist=[50.0*np.exp(-2.21)*浮点(met)]*len(speclist)
elif浮动(met)0.0052:
DGRlist=[50.0*np.exp(-2.21)*金属丰度]*len(规格表)#尘气比

elif金属丰度仍不可读。函数不应该那么长。@首先,这不能解决我的性能问题。其次,最终目标是能够简单地使用许多不同的参数调用
dust(…)
,而不必做任何其他事情,不幸的是,它需要许多任务/代码行。请尝试在子函数中对此进行分解。这真的很难理解(包括你自己在3个月内…)将代码放入函数并不会显著降低速度,如果有的话。这里还有一些事情很难发现,因为你的代码对于缺乏你的领域专业知识的人来说很难理解。我注意到在第一个示例中,您在一个循环中调用了一个scipy函数kinterp。在第二个循环中,您调用了一个python函数interpolate,它似乎是一个类似的循环。但它们并不是等价的,因为插值是一个非常复杂的函数,在调用kinterp之前需要进行一系列的数字运算。这可能是您的性能问题。将其分解为更小的函数所造成的性能损失应该可以忽略不计
import re
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate

# Required files and lists
filename = 'bpass_spectra.txt' # number of columns = 4
extinctionfile = 'ExtinctionLawPoints.txt' # R_V = 4.0
datalist = []
if filename == 'bpass_spectra.txt':
    filetype = 4
else:
    filetype = 1
if extinctionfile == 'ExtinctionLawPoints.txt':
    R_V = 4.0
else:
    R_V = 1.0 #to be determined

# Constants
M_sun = 1.98892e30 # solar mass [kg]
h = 4.1357e-15 # Planck's constant [eV s]
c = float(3e8) # speed of light [m/s]

# Inputs
beta = 2.0
R = 1.0
z = 1.0
M_gas = 1.0
M_halo = 2e41

# Read spectra file
f = open(filename, 'r')
rawlines = f.readlines()
met = re.findall('Z\s=\s(\d*\.\d+)', rawlines[0])
del rawlines[0]
for i in range(len(rawlines)):
    newlist = rawlines[i].split(' ')
    datalist.append(newlist)

# Read extinction curve data file
rawpoints = open(extinctionfile, 'r').readlines()
def interpolate(R_V, rawpoints, Elist, j):
    pointslist = []
    if R_V == 4.0:
        for i in range(len(rawpoints)):
            newlst = re.split('(?!\S)\s(?=\S)|(?!\S)\s+(?=\S)', rawpoints[i])
            pointslist.append(newlst)
        pointslist = pointslist[3:]
        lambdalist = [float(item[0]) for item in pointslist]
        k_abslist = [float(item[4]) for item in pointslist]
        xvallist = [(c*h)/(lamb*1e-6) for lamb in lambdalist]
        k_interp = scipy.interpolate.interp1d(xvallist, k_abslist)
        return k_interp(Elist[j])

# Dust extinction function
def dust(interpolate, filetype, datalist, beta, R, z, M_gas, M_halo, met):
    speclist = []
    if filetype == 4:
        metallicity = float(met[0])
        Elist = [float(item[0]) for item in datalist]
        speclambdalist = [h*c*1e9/E for E in Elist]
        met1list = [float(item[1]) for item in datalist]
        speclist.extend(met1list)
        klist, Tlist = [None]*len(speclist), [None]*len(speclist)
        if metallicity > 0.0052:
            DGRlist = [50.0*np.exp(-2.21)*metallicity]*len(speclist) # dust to gas ratio
        elif metallicity <= 0.0052:
            DGRlist = [((50.0*metallicity)**3.15)*np.exp(-0.96)]*len(speclist)
        for i in range(len(speclist)):
            if Elist[i] <= 4.1357e-3: # frequencies <= 10^12 Hz
                klist[i] = 0.1*(float(Elist[i])/(1000.0*h))**beta # extinction law [cm^2/g]
            elif Elist[i] > 4.1357e-3: # frequencies > 10^12 Hz
                klist[i] = interpolate(R_V, rawpoints, Elist, i) # interpolated function's value at Elist[i]
        Mdustlist = [M_gas*DGR for DGR in DGRlist] # dust mass
        R_halo = 0.784*(0.27**2.0)*(0.7**(-2.0/3.0))*float(10/(1+z))*((M_halo/(1e8*M_sun))**(1.0/3.0))
        R_dust = 0.018*R_halo # [kpc]

        # Optical depth calculation
        Tlist = [3*Mdustlist[i]*klist[i]/(4*np.pi*R_dust) for i in range(len(speclist))]

        # Ingoing and outgoing luminosities as functions of wavelength
        Linlist = [float(spectra)*R for spectra in speclist]
        Loutlist = [Linlist[i]*np.exp(-Tlist[i]) for i in range(len(speclist))]

        return speclambdalist, Linlist, Loutlist

print dust(interpolate, filetype, datalist, beta, R, z, M_gas, M_halo, met)