将模块内的所有函数和类导入到python类中

Mon*_*LiH 5 python module class python-import python-3.x

我正在尝试将所有对象从子文件夹导入python 3.8中的类,并在努力寻找一种方法来这样做。我不想手动导入所有对象,因为要列出的文件太多:

class Foo:
    from bar import {
        one,
        two,
        three,
        # ...
    }
Run Code Online (Sandbox Code Playgroud)

当我使用星号导入所有函数和类(例如from bar import *)时,出现以下错误:

SyntaxError: import * only allowed at module level
Run Code Online (Sandbox Code Playgroud)

另外,我也不希望将所有内容放在子作用域下(例如import bar.package,将所有文件放在的package子包中bar),因为函数在运行时bar依赖于传递self,这意味着必须更改selfself.packageI的所有引用仅使用该类中的所有方法创建另一个文件夹,以便没有单个极长的文件。

所以我想我有三个问题:为什么不允许在一个类中全部导入,如何解决这个问题,还有更好的方法将多个方法拆分为不同的文件吗?

编辑:我看过这篇文章是我目前所拥有的,但是我不想使用手动导入所有内容,而是代替了手动导入所有内容*

编辑2:也许创建一个类的子方法作为包并将其作为self导入是可行的(例如import bar.package as self),但这可能会覆盖默认的self。例如说我有两个文件foo.pybar.py

# foo.py
def print_bar(self):
    print("bar")
Run Code Online (Sandbox Code Playgroud)
# bar.py
class Test:
    import foo as self
    def __init__(self):
        print("hi")
        self.one = 1

    def print_one(self):
        print(self.one)

if __name__ == "__main__":
    test_class = Test()
    test_class.print_one()
    test_class.self.print_bar(test_class)
Run Code Online (Sandbox Code Playgroud)

注意bar.py运行中的丑陋调用test_class.self.print_bar(test_class)。在这种情况下,python不会自动将类作为方法传递。如果我摆脱了test_class函数中传递的参数,它将无法运行并给出一个TypeError。我想避免self不惜一切代价使用该方法。

Mar*_*ers 13

首先:不要这样做

解决您的特定问题可能有更好的方法。如果您必须为一个类定义大量相关方法,并且想使用模块来组织这些方法,则为每个模块提供一个基类,在这些类上定义方法,然后将模块中的类组合为一个使用子分类。见下文。

为什么不允许在一个类中全部导入

因为类语句是作用域内的命名空间,所以在编译时 Python 需要知道哪些名称被称为全局名称,并将其与本地名称区分开。这在函数中尤其重要,在函数中,通过知道编译时使用什么名称来高度优化了本地名称空间。对于类声明,“本地”名称成为类属性。当涉及到动态本地名称时,类语句比函数更灵活,但是将任意的动态名称列表导入类定义从未被认为是值得支持的用例。

我该如何解决

您可以内省模块并获取与Python导入的所有相同的名称,然后使用setattr()或通过分配给locals()字典来动态地在类上设置这些名称(类语句是后者实际起作用的唯一位置)。该import语句文档列出哪些是进口的:

  • 如果模块定义__all__,则将其用作要导入的名称列表
  • 否则,将导入所有公用名(所有全局名称不以开头的全局名称_)。

因此,以下内容将达到与from bar import *在class语句中使用以下内容完全相同的效果Foo

import bar

def _import_all(module, class):
    namespace = vars(module)
    public = (name for name in namespace if name[:1] != "_")
    for name in getattr(module, "__all__", public):
        setattr(class, name, namespace[name])

class Foo:
    pass

_import_all(bar, Foo)
Run Code Online (Sandbox Code Playgroud)

或者,这绝对是“ hack-y”,并取决于内部Python实现细节:

import bar

class Foo
    locals().update(
        (n, getattr(bar, n))
        for n in getattr(
            bar, "__all__",
            (n for n in dir(bar) if n[:1] != "_")
        )
    )
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法可以将多种方法拆分为不同的文件?

是的,使用类。将所有这些方法放在单独的模块中,每个模块放在一个类中,然后从每个模块中导入这些类并将其用作基类:

import bar, spam

class Foo(bar.Base, spam.Base):
    pass
Run Code Online (Sandbox Code Playgroud)

在哪里bar.py定义一个Base类:

class Base:
    def print_bar(self):
        print("bar")
Run Code Online (Sandbox Code Playgroud)

等等spam。您可以根据需要向这些基础mixin类添加和删除方法,并且import用于合并基础类的语句将不会更改。