gpt4 book ai didi

Python 命名空间元素可见性(与正确的包结构相比)

转载 作者:行者123 更新时间:2023-12-01 05:33:46 30 4
gpt4 key购买 nike

Python3

试图找到答案但失败了。首先,我将介绍该片段,然后我将解释我为什么要这样做以及我想要实现的目标。也许它看起来像这种方法是“坏的”。
因此,这个半双主题,首先我想知道为什么这个片段不起作用,其次 - 我想知道这种方法是否正确。

所以:

class Namespace:
def some_function():
pass

class SomeClass:
fcnt = some_function

这将不起作用,因为:
NameError: name 'some_function' is not defined
我想要实现的是代码和文件结构的可读性。

上面的例子是我在 Pyramid 项目中使用的一个片段(不是这个,但它看起来像这样)。

我的项目树如下所示:
my_project
├── models
│   ├── __init__.py
│   └── some_model.py
├── schemas
│   ├── __init__.py
│   ├── some_schema.py
│   └── some_other_schema.py
...
├── views
│   ├── __init__.py
│   └── some_view.py
└── __init__.py

我想要实现的是干净的模式/模型/ View 导入。

some_schema.py 文件位于 class SomeSchema , 在 some_other_schema.py class SomeOtherSchema .

使用上面的代码片段,我可以制作: from my_project.schemas.some_schema import Schema
并像 Schema.SomeSchema() 一样使用它

我对包裹和 import 有点迷失了。 s。如何制作一个干净的结构(每个文件一个模式)并且仍然能够使用 Schema 命名空间? (在 C++ 中,我只是将这些类中的每一个放在 Schema 命名空间中,这就是我在上面的片段中这样做的原因。但是!在 C++ 中有效的东西可能不应该在 python 中使用,对吧?)。

感谢您提前回答。

编辑:
好的,我已经做了一些测试(我以为我已经完成了,但看起来没有..)。
  • 使用 from my_project.schemas.some_schema import Schema与另一个 from my_project.schemas.some_other_schema import Schema导致第二个导入遮蔽第一个。因此,如果在第一次导入后我可以使用 x = Schema.SomeSchema()比第二次导入后我无法做到这一点,因为 class Schema被覆盖。对,正如 Erik 所说——类不是命名空间。知道了!
  • 在我的第一个片段中是的,我应该使用 fnct = Namespace.some_function .有什么奇怪的 - 它有效。我的 Pyramid 代码中有相同的声明,但有一点不同。 some_function@colander.deferred装饰师。实际上它看起来像这样:
    class Schema:
    @colander.deferred
    def deferred_some_function(node, kw):
    something = kw.get("something", [])
    return deform.widget.SelectWidget(values=something,
    multiple=True)

    class SomeSchema(colander.MappingSchema):
    somethings = colander.SchemaNode(colander.Set(),
    widget=Schema.deferred_some_function)

    我得到 NameError: name 'Schema' is not defined
  • 回到包格式。有了这个:
    ### another/file.py
    from foo.bar.schema import SomeSchema

    # do something with SomeSchema:
    smth = SomeSchema()
    smth.fcnt()

    我要做一个模块foo/bar/schema.py我必须把我所有的SomeXSchema类。如果我有很多,那么我想通过拆分 SomeXSchema 来消除不可读的故障 - 每个文件一个。我能以某种方式做到这一点吗?我想调用这个类,例如:User .事情就是这样。也许我做错了?我想要一个名为 User 的类在 schema命名空间和类 Usermodel命名空间。我不应该吗?也许我应该使用前缀?点赞class SchemaUserclass ModelUser ?我想通过使用模块/包来避免它。
    如果我使用:import foo.bar.schema那么我必须像 x = foo.bar.schema.User() 一样使用它正确的?没有办法像 x = schema.User() 那样使用它?对不起,我刚刚卡住了,我的大脑已经修复了。也许我需要休息一下重新审视一下?

    另一个编辑(仅针对第 3 点)

    我做了更多的研究。这里的答案是让它像这样:
    ## file: myproject/schemas/__init__.py
    from .some_schema import SomeSchema
    from .some_other_schema import SomeOtherSchema

    那么用法将是这样的:
    ## some file using it
    import myproject.schemas as schema
    s1 = schema.SomeSchema()
    s2 = schema.SomeOtherSchema()

    会是乐理艺术吗?
  • 如果有人认为应该更改该主题 - 请继续,给我一些更有意义的东西,我将不胜感激。
  • 最佳答案

    您正在通过尝试做您想做的事情而逆流而上。

    类旨在定义新的数据类型,而不是将相关的代码部分组合在一起。模块非常适合这一点,我想你很清楚问题标题中的“(与适当的包结构)”部分。

    模块也可以作为对象导入,所以要实现你想要的:

    ### foo/bar/schema.py
    def some_function():
    pass
    class SomeSchema:
    fcnt = some_function


    ### another/file.py
    from foo.bar import schema

    # do something with SomeSchema:
    smth = schema.SomeSchema()
    smth.fcnt()

    ...尽管将类直接导入这样的范围也是典型的(即能够在导入后引用 SomeSchema 而不是 schema.SomeSchema ):
    ### another/file.py
    from foo.bar.schema import SomeSchema

    # do something with SomeSchema:
    smth = SomeSchema()
    smth.fcnt()

    (另请注意,模块名称应为 PEP8 所建议的小写,并且只有类名称应使用 PascalCase )

    顺便说一句,这适用于一般的编程,而不仅仅是 Python。有一些语言,如 Java 和 C#,要求在类内部将函数声明为静态函数,因为它们出于某种奇怪的原因不允许在类之外编写代码,但即使这些语言也有模块/适当的命名空间来构建代码;即类通常不会放在其他类中(有时它们会放在其他类中,但原因/目标与您的完全不同)。

    所以基本上“类”是指“类型”或“一组具有相似行为的对象”;一旦你忽略了这个原则/定义,你就按照定义编写了糟糕的代码。

    PS。 如果你使用 Python 2.x,你应该从 object 继承你的类从而得到 new-style类。

    聚苯乙烯。 在任何情况下,即使从技术上讲,您尝试做的事情在 Python 中都无法正常工作:
    class fake_namespace:
    def some_function():
    pass
    class RealClass:
    some_function # <-- that name is not even visibile here;
    # you'd have to use fake_namespace.some_function instead

    ...这就是我报告我得到的异常的原因:NameError: name 'some_function' is not defined。

    根据您的编辑进行编辑:

    我不太确定你为什么把它弄得这么复杂。你的一些陈述也是错误的:

    If I'd use : import foo.bar.schema then I'd have to use it like x = foo.bar.schema.User right?



    不,请了解 Python 模块的工作原理。

    I'd like to have class named User in Schema namespace and class named User in Model namespace. Shouldn't I? Maybe I ought to use prefix? Like class SchemaUser and class ModelUser



    请注意命名空间(也称为模块)应为 lowercase不是 PascalCase .

    An if I have lots of them, then there's the unreadabilty glitch which I wanted to get rid off by splitting SomeXSchema - one per file. Can I accomplish this somehow?



    是的;你可以把你的类放在单独的子模块中,例如 schema1/class1.py , schema/class2.py等等;然后您可以将它们“收集”到 schema/__init__.py这样您就可以直接从 schema 导入它们:
    # schema/__init__.py
    from .class1 import Class1
    from .class2 import Class2

    __all__ = [Class1, Class2] # optional

    一般说明:您可以以不同的方式命名您的架构模块,例如 schema1 , schema2 , 等等;那么你可以像这样使用它们:
    from somewhere import schema1
    from somewhere_else import schema2

    s1_user = schema1.User()
    s2_user = schema2.User()
    # etc

    有关 Python 模块如何工作的更多信息,请参阅 http://docs.python.org/2/tutorial/modules.html

    关于Python 命名空间元素可见性(与正确的包结构相比),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19604298/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com