>백엔드 개발 >파이썬 튜토리얼 >Python에서 순환 가져오기 방법을 피하는 방법에 대한 소개

Python에서 순환 가져오기 방법을 피하는 방법에 대한 소개

巴扎黑
巴扎黑원래의
2017-09-16 10:07:481486검색

대규모 Python 프로젝트에서는 부적절한 아키텍처 설계로 인해 모듈 간의 상호 참조가 발생할 수 있습니다. 다음 글에서는 Python의 순환 가져오기 문제를 방지하는 방법에 대한 관련 정보를 주로 소개합니다. 도움이 필요한 친구들이 참고할 수 있습니다.

서문

Python에서 패키지를 사용할 때 순환 가져오기 문제가 발생하는 것은 매우 일반적입니다. 이 문제를 설명하기 위해 다음 패키지를 만들었습니다.


pkg
 ├── __init__.py
 ├── module_a.py
 └── module_b.py

그 중

__init__.py pkg를 Python 패키지로 지정

module_a.py는 module_b.py에 정의된 함수나 변수와 같은 module_b.py의 속성을 참조하는 action_a() 함수를 정의합니다. A action_b() 함수, 함수 또는 변수와 같은 module_a.py의 속성을 참조합니다 action_a()函数,该函数引用了module_b.py中的一个attribute,如一个函数或变量

module_b.py中定义了一个action_b()函数,该函数引用了module_a.py中的一个attribute,如一个函数或变量

这种情况下,执行该package时会抛出circular import error错误,即循环引用,因为module_a试图去引入module_b时,而module_b首先要引入module_a,这会导致Python解释器无法执行下去。

然而,我们可以通过一些巧妙的方法,让上面的逻辑正常工作,同时避免循环引入的错误。

那么,什么时候它能正常工作,什么时候不能正常工作,而那些能够正常工作的情况又是什么原因呢?

何时它能正常工作?

 1. 在module顶部引入,不要用from,相对引入,只在Python 2中有效

在module的顶部import,如import another_module,module 中的函数以another_module.attribute的方式引用another_module中的函数或变量等。这种方式之所以有效,是由于import another_module是基于当前目录的相对引用,而且是一种隐式引用,如果从另一个package中引入module时,就可以失效了。另外,import another_module这种语法在Python3 中已经不支持了,所以不要在代码中用这种方法来避免循环引入。

如:


# pkg/module_a.py 
from __future__ import print_function
import module_b
 
def action_a():
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import module_a
 
def action_b():
 print(module_a.action_a.__name__)

2. 在module的顶部引入,不要用from,绝对引入

在module的顶部import,使用从package开始的绝对路径,如import package.another_module,module 中的函数以package.another_module.attribute的方式引用another_module中的函数或变量等。之所以要挂上package name来引入,是由于import .another_module这种形式的“相对引入”会报语法错误,而挂上package的绝对引入,Python 2和3都支持

案例:


# pkg/module_a.py
from __future__ import print_function
import pkg2.module_b
 
def action_a():
 print(pkg2.module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import pkg2.module_a
 
def action_b():
 print(pkg2.module_a.action_a.__name__)

3. 在module底部引入another module的attribute,而非another module,用from

在module的底部import(至少要在被引用的attribute之后import),直接引入another module的attribute,如from package.another_module import attribute,相对引入也支持,如from .another_module import attribute,module中的函数直接使用被引用的attribute即可。

如:


# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 print(action_b.__name__)
 
from .module_b import action_b
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 print(action_a.__name__)
 
from .module_a import action_a

4. 函数顶部引入,可以用from

在module的function顶部import,如from package import another_module

이 경우 패키지 오류 실행 시 순환 가져오기가 발생합니다 오류, 즉 순환 참조입니다. module_a가 module_b를 도입하려고 시도하고 module_b가 먼저 module_a를 도입하여 Python 인터프리터가 실행될 수 없게 되기 때문입니다.

그러나 몇 가지 영리한 방법을 사용하면 루프로 인한 오류를 피하면서 위의 논리가 제대로 작동하도록 만들 수 있습니다.

그럼 언제 제대로 작동하고, 언제 제대로 작동하지 않고, 제대로 작동하는 경우의 이유는 무엇인가요?


언제부터 제대로 작동되나요?

1. 모듈 상단에서 가져오기, from을 사용하지 않음, 상대 가져오기, Python 2

import another_module)에서 모듈 상단에서 가져오기만 가능 >, 모듈의 함수 another_module.attribute 형식의 another_module에 있는 함수 또는 변수를 참조하세요. 이 방법이 효과적인 이유는 import another_module이 현재 디렉터리를 기준으로 한 상대 참조이며, 다른 패키지에서 모듈을 가져오면 유효하지 않게 되기 때문입니다. 또한 import another_module 구문은 Python 3에서 더 이상 지원되지 않으므로 루프 도입을 방지하려면 코드에서 이 메서드를 사용하지 마세요.


예:

🎜🎜
# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from . import module_b
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 from . import module_a
 print(module_a.action_a.__name__)
🎜🎜2. 모듈 상단에서 가져오기, 원본에서 사용하지 않음, 절대 가져오기 🎜🎜🎜🎜모듈 상단에서 가져오기, 패키지에서 시작하는 절대 경로 사용, import package .another_module과 같이 module의 함수는 package.another_module.attribute 형식의 another_module에 있는 함수나 변수를 참조합니다. 가져올 패키지 이름을 걸어 놓아야 하는 이유는 import .another_module 형식의 "상대 가져오기"는 구문 오류를 보고하는 반면, 패키지의 절대 가져오기는 지원되기 때문입니다. Python 2 및 3 모두🎜 🎜🎜사례: 🎜🎜🎜🎜
# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from .module_b import action_b
 print(action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
def action_b():
 from .module_a import action_a
 print(action_a.__name__)
🎜🎜3. 다른 모듈 대신 from🎜🎜🎜🎜을 사용하여 모듈 하단에 가져옵니다. 모듈(적어도 참조된 속성 이후에 가져오기), package.another_module 가져오기 속성에서와 같이 다른 모듈의 속성을 직접 도입하는 것도 지원됩니다. code>from .another_module 가져오기 속성, 모듈 내 함수는 참조된 속성을 직접 사용할 수 있습니다. 🎜🎜🎜예: 🎜🎜🎜🎜rrreee🎜🎜4 함수 상단에서 가져오려면 from🎜🎜🎜🎜을 사용하여 from과 같이 모듈의 함수 상단에서 가져올 수 있습니다. package import another_module, 상대 가져오기도 지원합니다. 모듈이나 속성을 도입할 수 있습니다. 🎜🎜🎜 예: 🎜🎜🎜🎜rrreee🎜 또는 🎜🎜🎜🎜rrreee🎜 이 방법은 Python 2 및 3에서 지원되지만 코딩이 충분히 우아하지 않으며 코드의 가독성에 영향을 미치므로 사용하지 않는 것이 좋습니다. 🎜🎜🎜🎜🎜Note🎜 🎜🎜🎜🎜이 글에서 논의한 문제는 Python에서 패키지를 호출할 때 루프 도입을 피하는 방법입니다.🎜🎜🎜Python 모듈이 명령줄에서 직접 실행될 때 적용 가능한 상황은 정확히는 아닙니다. 똑같아🎜

위 내용은 Python에서 순환 가져오기 방법을 피하는 방법에 대한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.