Python: 全局使用局部变量不起作用

Python: Use local variable globally does not work

我正在尝试使用我的代码在任一操作系统中搜索文件后打开它。但是,当我在函数内部分配变量时,我不能在函数外部使用它。当我将第二个功能保留在第一个功能之外时,它无法识别该功能。

我尝试全局分配 df_location,但这不起作用。 当我在函数内部使用 df = pd.read_csv(df_location[0], index_col=0) 时,我无法在我的代码中的其他任何地方使用 df。

if platform.system() == 'windows':
    def find_file(root_folder, rex):
        for root, dirs, files in os.walk(root_folder):
            for f in files:
                result = rex.search(f)
                if result:
                    file_path = os.path.join(root, f)
                    return file_path  

    def find_file_in_all_drives(file_name):

        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('[=11=]0')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

    global df_location
    df_location = find_file_in_all_drives("AB_NYC_2019.csv")

if platform.system() == 'mac':
    df_location = find_file("/", "AB_NYC_2019.csv")


df = pd.read_csv(df_location[0], index_col=0)

我希望能够使用通过函数检索到的文件。

谢谢!

理想情况下应该是这样的

if platform.system() == 'windows':
    def find_file(root_folder, rex):
        for root, dirs, files in os.walk(root_folder):
            for f in files:
                result = rex.search(f)
                if result:
                    file_path = os.path.join(root, f)
        return file_path  

    def find_file_in_all_drives(file_name):

        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('[=12=]0')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

df_location = find_file_in_all_drives("AB_NYC_2019.csv")

if platform.system() == 'mac':
    df_location = find_file("/", "AB_NYC_2019.csv")


df = pd.read_csv(df_location[0], index_col=0)

但这给出了错误信息: "NameError: name 'find_file_in_all_drives' is not defined"

您没有显示所有代码。据推测,您也有 mac 的 find_filefind_file_in_all_drives 函数实现,是吗?至少这是我仅通过查看您发布的代码所期望的。

如果这真的是您所有的代码,那么按照现在的编写方式,您只定义 find_filefind_file_in_all_drives if platform.system() returns "windows"(旁注:刚刚试过,在我的 Windows 7 系统上它 returns "Windows" 大写 'W'。)如果不满足该条件,则这些函数定义在代码的其他任何地方都不可见,因为您已将它们放在 if 语句的主体内。

您似乎在尝试根据字符串的内容获得不同的行为 (platform.system())。由于您无法避免为两个操作系统实现不同的行为,因此您可以为此使用多态性:

import abc


class DataFrameFinder(abc.ABC):

    def __init__(self):
        pass

    @abc.abstractmethod
    def find_file(self, root_folder, rex):
        raise NotImplementedError

    @abc.abstractmethod
    def find_file_in_all_drives(self, file_name):
        raise NotImplementedError


class DataFrameFinderWindows(DataFrameFinder):

    def __init__(self, *args, **kwargs):
        DataFrameFinder.__init__(self, *args, **kwargs)

    def find_file(self, root_folder, rex):
        # Do windows things...
        pass

    def find_file_in_all_drives(self, file_name):
        # Do windows things...
        pass


class DataFrameFinderMac(DataFrameFinder):

    def __init__(self, *args, **kwargs):
        DataFrameFinder.__init__(self, *args, **kwargs)

    def find_file(self, root_folder, rex):
        # Do mac things...
        pass

    def find_file_in_all_drives(self, file_name):
        # Do mac things...
        pass

def main():

    import platform

    finder_factory = {
        "Windows": DataFrameFinderWindows,
        "Mac": DataFrameFinderMac
    }

    finder = finder_factory[platform.system()]()

    finder.find_file(...)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

您为 Window 定义了 find_file_in_all_drives,但您也应该为其他系统定义 find_file_in_all_drives - 但每个系统在 find_file_in_all_drives 中都有不同的代码。然后你可以在每个系统上使用 find_file_in_all_drives

# all systems use it so it should be defined for all

def find_file(root_folder, rex):
    for root, dirs, files in os.walk(root_folder):
        for f in files:
            result = rex.search(f)
            if result:
                file_path = os.path.join(root, f)
    return file_path  

# define different `find_file_in_all_drives` for different systems     

if platform.system() == 'windows':

    def find_file_in_all_drives(file_name):
        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('[=10=]0')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

if platform.system() in ('mac', 'linux'):

    def find_file_in_all_drives(file_name):
        return find_file("/", file_name)

# now you can use `find_file_in_all_drives` on every system

df_location = find_file_in_all_drives("AB_NYC_2019.csv")

df = pd.read_csv(df_location[0], index_col=0)