当前位置: 首页 > 面试题库 >

python循环再次导入(又是该设计有什么问题)

酆阳煦
2023-03-14
问题内容

让我们考虑python(3.x)脚本:

main.py:

from test.team import team
from test.user import user

if __name__ == '__main__':
    u = user()
    t = team()
    u.setTeam(t)
    t.setLeader(u)

测试/user.py:

from test.team import team

class user:
    def setTeam(self, t):
        if issubclass(t, team.__class__):
            self.team = t

测试/team.py:

from test.user import user

class team:
    def setLeader(self, u):
        if issubclass(u, user.__class__):
            self.leader = u

现在,当然,我有循环导入和出色的ImportError了。

因此,不是Pythonista,我有三个问题。首先:

一世。我该如何使这件事起作用?

而且,知道有人不可避免地会说“圆形导入始终表示设计问题”,第二个问题是:

ii。为什么这个设计不好?

最后是第三个:

iii。有什么更好的选择?

确切地说,上面的类型检查只是一个例子,还有一个基于类的索引层,即允许。查找所有用户都属于一个团队的成员(用户类具有许多子类,因此对于一般用户和每个特定子类而言,索引加倍)或已将用户作为成员的所有团队

编辑:

我希望有更详细的例子来阐明我要达到的目标。为了便于阅读而省略了文件(但是有一个300kb的源文件以某种方式使我感到恐惧,因此请假定每个类都在不同的文件中)

# ENTITY

class Entity:
    _id    = None
    _defs  = {}
    _data  = None

    def __init__(self, **kwargs):
        self._id   = uuid.uuid4() # for example. or randint(). or x+1.
        self._data = {}.update(kwargs)

    def __settattr__(self, name, value):
        if name in self._defs:
            if issubclass(value.__class__, self._defs[name]):
                self._data[name] = value

                # more stuff goes here, specially indexing dependencies, so we can 
                # do Index(some_class, name_of_property, some.object) to find all   
                # objects of some_class or its children where
                # given property == some.object

            else:
                raise Exception('Some misleading message')
        else:
            self.__dict__[name] = value

    def __gettattr__(self, name):
        return self._data[name]

# USERS

class User(Entity):
    _defs  = {'team':Team}

class DPLUser(User):
    _defs  = {'team':DPLTeam}

class PythonUser(DPLUser)
    pass

class PerlUser(DPLUser)
    pass

class FunctionalUser(User):
    _defs  = {'team':FunctionalTeam}

class HaskellUser(FunctionalUser)
    pass

class ErlangUser(FunctionalUser)
    pass

# TEAMS

class Team(Entity):
    _defs  = {'leader':User}

class DPLTeam(Team):
    _defs  = {'leader':DPLUser}

class FunctionalTeam(Team):
    _defs  = {'leader':FunctionalUser}

现在一些用法:

t1 = FunctionalTeam()
t2 = DLPTeam()
t3 = Team()

u1 = HaskellUser()
u2 = PythonUser()

t1.leader = u1 # ok
t2.leader = u2 # ok
t1.leader = u2 # not ok, exception
t3.leader = u2 # ok

# now , index

print(Index(FunctionalTeam, 'leader', u2)) # -> [t2]
print(Index(Team, 'leader', u2)) # -> [t2,t3]

因此,除了这种不完善的循环导入之外,它还可以很好地工作(省略了实现细节,但没有什么复杂的事情)。


问题答案:

循环进口本质上不是一件坏事。team代码自然地依赖,user而使用进行user某些操作team

这里最糟糕的做法是from module import member。该team模块正在尝试user在导入时获取该类,而该user模块正在尝试获取team该类。但是team该类尚不存在,因为您仍处于team.pywhenuser.py运行的第一行。

而是,仅导入模块。这样可以更清晰地命名空间,使以后的猴子修补成为可能,并解决了导入问题。因为您只是在导入时导入 模块 ,所以您不在乎尚未定义 模块
中的 。等到您开始使用该类时,它就会成为现实。

因此,test / users.py:

import test.teams

class User:
    def setTeam(self, t):
        if isinstance(t, test.teams.Team):
            self.team = t

测试/teams.py:

import test.users

class Team:
    def setLeader(self, u):
        if isinstance(u, test.users.User):
            self.leader = u

from test import teams然后teams.Team,如果您想test少写,也可以。那仍然是导入模块,而不是模块成员。

另外,如果TeamUser比较简单,请将它们放在同一模块中。您无需遵循Java每个文件一个类的习惯用法。该isinstance测试和set方法也尖叫unpythonic-
Java的疣给我; 根据您在做什么,最好使用普通的,非类型检查的@property



 类似资料:
  • 问题内容: 所以我得到这个错误 并且你可以看到我进一步使用了相同的import语句,并且可以正常工作吗?关于循环导入是否有一些不成文的规定?如何在调用堆栈的更下方使用同一类? 问题答案: 我认为jpmc26的答案虽然绝非错误,但在循环进口上却过于严格。如果正确设置它们,它们可以正常工作。 最简单的方法是使用语法,而不是。前者几乎总是可以工作,即使包括在内也能使我们重新获得利益。后者只有在中已经定义

  • 问题内容: 据我了解,python模块永远不会导入两次,即该模块中的代码仅在首次导入时才执行。随后的import语句只需将模块添加到导入范围即可。 我有一个名为“ TiledConvC3D.py”的模块,但似乎已多次导入。我使用pdb在该模块的代码顶部打印堆栈。 这是从第一次执行模块开始的堆栈跟踪的结尾: 它将继续执行多次。但是,第二次调用的完整堆栈跟踪不会显示对的任何调用,因此不应执行这些执行:

  • 问题内容: 如果两个模块相互导入会怎样? 为了概括这个问题,Python中的循环导入又如何呢? 问题答案: 导入确实非常简单。只要记住以下几点: 和是可执行语句。它们在运行的程序到达该行时执行。 如果模块不在中,则导入将在中创建新的模块条目,然后在模块中执行代码。在执行完成之前,它不会将控制权返回给调用模块。 如果中确实存在一个模块,则无论导入是否完成执行,导入都会简单地返回该模块。这就是循环导入

  • 在循环一节,我们已经讨论了 Python 基本的循环语法。这一节,我们将接触更加灵活的循环方式。 range() 在Python中,for循环后的in跟随一个序列的话,循环每次使用的序列元素,而不是序列的下标。 之前我们已经使用过range()来控制for循环。现在,我们继续开发range的功能,以实现下标对循环的控制: S = 'abcdefghijk' for i in range(0,len

  • 问题内容: 我真的没有得到这个,所以如果有人可以解释它是如何工作的,我将非常感激。我有两个应用程序,“帐户”和“主题” …这是我的设置列表: 在帐户中,我正在尝试执行以下操作: 在我的主题模型中: Django踢出以下错误: 这是某种循环进口问题吗?我尝试使用一个懒惰的引用,但这似乎也不起作用! 问题答案: 删除的导入,并将模型名称用作字符串。

  • 我正在PL/SQL上练习集合,现在我编写了一个简单的WHILE循环,以便在屏幕上打印稀疏关联数组的值。我收到以下错误:Oracle错误-06502:PL/SQL:数值或值错误:NULL索引表键值。结果打印在屏幕上,但oracle也出错了。谢了。 Informe de error-ORA-06502:PL/SQL:数值或值error:NULL索引表键值ORA-06512:在第48行065 02。00