0

新しいクラス インスタンスを作成するときに、別のクラスのメソッドを呼び出そうとしていますが、動作させることができません。ここに私が持っているものがあります:

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.xlxsNameError: global name 'read_xlsx' is not definedを使用してこれを実行すると、Python の知識に大きな穴を発見したと思いました (それほど多くないというわけではありませんが、見にくい傾向があります。大きな森...)。

私はgetattr(Analysis(), ... )、Analysis クラスとそのメソッドを見つけるグローバルな名前空間にアクセスすると考えていたでしょう。実際print(globals().keys())、Analysis がこの一部であることを示しています。

['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)
4

2 に答える 2

2

完全なトレースバックから、DataProjectクラスがメソッドを (正常に) 呼び出しており、そのAnalysys.read_xlsメソッドが を呼び出そうとしているように見えますread_xlsx。ただし、メソッドとしてではなく、グローバル関数として呼び出しています。

おそらく、90 行目のコードを に置き換える必要があるだけですが、親インスタンスにも追加のパラメーターread_xlsx(input_file)self.read_xlsx(input_file)渡す必要があるかもしれません。DataProject

于 2013-09-08T00:46:35.140 に答える
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)。メソッドの命名は、プログラムのロジックの中核部分であってはなりません。- 関数の呼び出しと定義のたびに関数の名前をいつでも変更でき、プログラムの動作をそのままにしておくことができる必要があります。

ファイル形式を特定のメソッドで処理する必要がある場合、このロジックは、これを担当するユニット (関数など) に委譲する必要があります。これを行う1 つの方法 (他にもあります) は、入力を受け取り、それを処理する必要がある関数を決定する関数を用意することです。

def read_file(self,file,format):
    if format == `xls`:
        self.read_xls(file)
    if format == `csv`:
        self.read_csv(file)

上記のスニペットにも問題があります (より適切な方法は、たとえば、一連の責任パターンです) が、小さなスクリプトには問題なく、はるかに優れています。

于 2013-09-08T00:41:18.133 に答える