在创建新的类实例时,我正在尝试在不同的类中调用方法,但无法使其工作。这就是我所拥有的:
class DataProject(object):
def __init__(self, name=none,input_file=None,datamode=None,comments=None,readnow=True):
..............
# here's where I'm trying to call the method in the other class
if type(input_file) == str:
self.input_file_format = self.input_file.split(".")[-1]
if readnow:
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
class Analysis(object):
def __init__(self):
pass # nothing happens here atm
def read_xlsx(self,parent,input_file):
"""Method to parse xlsx files and dump them into a DataFrame"""
xl = pd.ExcelFile(input_file)
for s in sheet_names:
parent.data[s]=xl.parse(s)
当我使用afile.xlxs作为输入运行时,我得到一个NameError: global name 'read_xlsx' is not defined
,这让我觉得我刚刚发现了我的Python知识中的一个大洞(并不是说有很多但他们倾向于很难看到,有点像大森林......)。
我原以为getattr(Analysis(), ... )
会访问全局名称空间,在该空间中可以找到Analysis类及其方法。事实上,print(globals().keys())
表明分析是其中的一部分:
['plt', 'mlab', '__builtins__', '__file__', 'pylab', 'DataProject', 'matplotlib', '__package__', 'W32', 'Helpers', 'time', 'pd', 'pyplot', 'np', '__name__', 'dt', 'Analysis', '__doc__']
我在这里缺少什么?
编辑:
完整的追溯是:
Traceback (most recent call last):
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 101, in <module>
a=DataProject(input_file='C:\\MPython\\dataAnalysis\\EnergyAnalysis\\afile.xlxs',readnow=True)
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 73, in __init__
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
File "C:\MPython\dataAnalysis\dataAnalysis.py", line 90, in read_xls
read_xlsx(input_file)
NameError: global name 'read_xlsx' is not defined
我的主要电话是:
if __name__=="__main__":
a=DataProject(input_file='C:\\MPython\\dataAnalysis\\EnergyAnalysis\\afile.xlx',readnow=True)
答案 0 :(得分:2)
getattr()
的工作原理与您在Python2.x和Python3.x中描述的一样。错误必须在其他地方。
您对代码的修改(没有更改核心逻辑)可以正常工作:
class DataProject(object):
def __init__(self, name="myname",input_file="xlsx",datamode=None,comments=None,readnow=True):
if type(input_file) == str:
self.input_file_format = input_file.split(".")[-1]
if readnow:
getattr(Analysis(),'read_'+self.input_file_format)(self,input_file)
class Analysis(object):
def __init__(self):
pass # nothing happens here atm
def read_xlsx(self,parent,input_file):
"""Method to parse xlsx files and dumpt them into a DataFrame"""
print("hello")
a=DataProject()
输出是:
$ python3 testfn.py
hello
getattr()
通常是一个坏主意您使用getattr
的方式会强制您的方法(read_someformat
)的命名约定。 您的方法的命名不应该是程序逻辑的核心部分。 - 您应该始终能够在每次调用和定义该函数时更改函数的名称,并保持程序的行为不变。
如果需要通过特定方法处理文件格式,则应将此逻辑委派给负责此操作的某个单元(例如函数)。这样做的一种方式(其中是其他方法)是有一个函数接受输入并决定哪个函数需要处理它:
def read_file(self,file,format):
if format == `xls`:
self.read_xls(file)
if format == `csv`:
self.read_csv(file)
上面的代码片段确实也有它的问题(例如,更好的方法是chain of responsibility pattern)但是对于小脚本来说它会更好并且更好。
答案 1 :(得分:2)
在完整的回溯中,您的DataProject
类似乎正在调用(成功)Analysys.read_xls
方法,而后者正在尝试调用read_xlsx
。但是,它将其称为全局函数,而不是方法。
可能您只需要替换第90行的代码,将read_xlsx(input_file)
转换为self.read_xlsx(input_file)
,但您可能还需要为父DataProject
实例传递额外的参数。