파이썬에서 IoC / DI가 일반적이지 않은 이유는 무엇입니까?


312

Java IoC / DI 는 웹 애플리케이션, 거의 모든 사용 가능한 프레임 워크 및 Java EE에서 광범위하게 사용되는 매우 일반적인 관행입니다. 다른 한편으로, 큰 파이썬 웹 응용 프로그램도 많이 있지만 Zope (코드가 정말 끔찍해야한다고 들었습니다) 외에도 IoC는 Python 세계에서 흔하지 않은 것 같습니다. (내가 틀렸다고 생각하면 몇 가지 예를 들어보십시오).

물론 파이썬, 예를 들어 스프링 피톤 에 사용할 수있는 널리 사용되는 Java IoC 프레임 워크의 여러 복제본이 있습니다 . 그러나 그들 중 누구도 실제로 사용되지 않는 것 같습니다. 적어도, 나는 그런 것을 사용하는 Django 또는 sqlalchemy + <insert your favorite wsgi toolkit here>기반 웹 응용 프로그램을 본 적이 없습니다 .

제 생각에 IoC는 합리적인 장점을 가지고 있으며 django-default-user-model을 쉽게 대체 할 수 있지만 파이썬에서 인터페이스 클래스와 IoC를 광범위하게 사용하는 것은 약간 이상하고»pythonic«이 아닙니다. 그러나 누군가 IoC가 파이썬에서 널리 사용되지 않는 이유에 대해 더 잘 설명하고 있습니다.


2
내 생각에 루비, 내장 믹스 인 및 오픈 클래스에서 덜 인기가있는 것과 같은 이유
Sam Saffron

3
스프링 피톤을 사용해 본 적이 있습니까? 그것은 광고 된대로 작동하지 않습니다. 적어도 aop 부분에서. Java에서 나오지 않고 전환 중에 어느 정도의 편안함이 필요하지 않으면 거기에있는 모든 것은별로 유용하지 않습니다.
Tom Willis

6
DI의 사용과 IOC 프레임 워크의 사용을 구별하도록주의하십시오. 전자는 디자인 패턴이며 후자는 전자의 자동 사용을 지원하는 프레임 워크입니다.
Doug

더그, DI는 데코레이터 패턴을 사용하여 얻을 수있는 창작 기능이라고 생각합니다.
njappboy

4
DI가 해결하는 실제 문제 (평생 관리, 테스트 스터 빙의 용이성 등)를 해결하는 답변을보고 싶습니다. 더 많은 파이썬적인 방법으로 문제를 해결할 수 있다면 저는 모두 귀입니다.
Josh Noe

답변:


197

실제로 DI / IOC의이 있다고 생각하지 않는다 파이썬에서 드문 일. 무엇 이다 드문 그러나, DI / IOC의의입니다 프레임 워크 / 컨테이너 .

DI 컨테이너의 기능은 무엇입니까? 그것은 당신이 할 수 있습니다

  1. 독립적 인 구성 요소를 완벽한 어플리케이션에 연결 ...
  2. ... 런타임에.

"함께 연결"과 "런타임"이라는 이름이 있습니다.

  1. 스크립팅
  2. 동적

따라서 DI 컨테이너는 다이나믹 스크립팅 언어의 해석 기일뿐입니다. 사실, 일반적인 Java / .NET DI 컨테이너는 엉덩이 기반, 때로는 XML 기반의 구문을 사용하는 매우 역동적 인 스크립팅 언어를위한 엉터리 해석 기일뿐입니다.

파이썬으로 프로그래밍 할 때, 아름답고 화려한 스크립팅 언어를 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까? 실제로는 더 일반적인 질문입니다. 거의 모든 언어로 프로그래밍 할 때 자이 썬과 아이언 파이썬을 사용할 때 왜 못생긴 나쁜 스크립팅 언어를 사용하고 싶습니까?

요약하자면, DI / IoC 의 관행 은 정확히 같은 이유로 Java에서와 마찬가지로 Python에서도 중요합니다. 그러나 DI / IoC 의 구현 은 언어에 내장되어 있으며 종종 너무 가벼워 완전히 사라집니다.

(여기에 유추 할 수있는 간단한 설명이 있습니다. 어셈블리에서 서브 루틴 호출은 상당히 중요한 일입니다. 로컬 변수와 레지스터를 메모리에 저장하고, 리턴 주소를 어딘가에 저장하고, 호출하는 서브 루틴에 대한 명령 포인터를 변경해야합니다. 서브 루틴이 끝나면 서브 루틴으로 되돌아 가도록하고, 수신자가 찾을 수있는 곳에 인수를 넣습니다. IOW : 어셈블리에서 "서브 루틴 호출"은 디자인 패턴이며 다음과 같은 언어가 있기 전에 서브 루틴 호출이 내장 된 포트란 사람들은 자신 만의 "서브 루틴 프레임 워크"를 구축하고있었습니다. 서브 루틴 프레임 워크를 사용하지 않기 때문에 서브 루틴 호출이 파이썬에서 "흔하지 않다"고 말할 수 있습니까?)

BTW : DI를 논리적으로 결론 짓는 모습에 대한 예를 보려면 Gilad BrachaNewspeak Programming Language 와 주제에 대한 글을 살펴보십시오 .


58
동의하지만 XML 주석이 잘못되었습니다. 많은 (적어도 현대적인) IOC 컨테이너는 컨피규레이션 (코드)에 대한 컨벤션 (XML)을 사용합니다.
Finglas

20
Java로 배선을 명시 적으로 작성하는 데 방해가되는 것은 없지만 점점 더 많은 서비스가있을수록 종속성이 더 복잡해집니다. DI 컨테이너는 Make와 같습니다. 종속성을 선언하면 컨테이너가 올바른 순서로 초기화합니다. Guice는 모든 것이 Java 코드로 작성된 Java DI 프레임 워크입니다. 선언적으로 DI 컨테이너를 작성함으로써 초기화 전에 편차를 사후 처리하기위한 지원도 추가합니다 (예 : 속성 자리 표시자를 실제 값으로 교체)
IttayD

133
"그러나 DI / IoC의 구현은 언어에 내장되어 있으며 종종 너무 작아서 완전히 사라집니다." 이것은 명백히 사실이 아니기 때문에 투표에 참여하십시오. DI는 인터페이스가 생성자로 전달되는 패턴입니다. 파이썬에는 내장되어 있지 않습니다.
Doug

146
downvote, 배선은 스크립팅과 관련이 없으며 DI는 패턴이며 스크립팅과 동일하지 않습니다
Luxspes

38
나는 이것에 동의하지 않습니다. DI는 정적 언어에서의 동적 스크립팅 부족을 해결하지 못합니다. 응용 프로그램 부분을 구성하고 구성하기위한 프레임 워크를 제공합니다. 나는 한때 루비 개발자가 동적 언어에서 DI가 필요하지 않다고 말합니다. 그러나 그는 Rails를 사용했습니다 ... Rails는 일종의 큰 DI 컨테이너로, 컨벤션을 사용하여 언제 어느 부분을 구성해야하는지 파악합니다. Rails가 부품 찾기 문제를 해결했기 때문에 DI가 필요하지 않았습니다.
Brian Genisio

51

그 중 일부는 파이썬에서 모듈 시스템이 작동하는 방식입니다. 모듈에서 가져 오기만하면 일종의 "단일"을 무료로 얻을 수 있습니다. 모듈에서 객체의 실제 인스턴스를 정의하면 모든 클라이언트 코드가 가져와 실제로 작동하고 완벽하게 구성 / 채워진 객체를 얻을 수 있습니다.

이는 실제 객체 인스턴스를 가져 오지 않는 Java와 대조적입니다. 즉, 항상 직접 인스턴스화해야합니다 (또는 일종의 IoC / DI 스타일 접근 방식 사용). 정적 팩토리 메소드 (또는 실제 팩토리 클래스)를 사용하여 모든 것을 직접 인스턴스화해야하는 번거 로움을 완화 할 수 있지만 매번 실제로 새 메소드를 작성하는 데 따른 자원 오버 헤드가 여전히 발생합니다.


2
말이 되네요 파이썬에서 구현을 변경하려면 동일한 이름을 사용하여 다른 위치에서 가져옵니다. 그러나 이제는 완전히 초기화 된 정적 인스턴스 만 포함하는 Java MyClassInstances로 각각 MyClass에 클래스를 정의하여 다른 방법으로 가능한지 생각하고 있습니다. 유선 : D
tux21b

2
그리고 또 다른 아이디어 : 파이썬에서 이러한 가져 오기를 변경하는 방법을 제공하면 모든 파이썬 파일을 건드리지 않고 구현을 쉽게 대체 할 수 있습니다. 대신 프레임 워크 안에 from framework.auth.user import User 작성하는 것이 좋습니다 User = lookup('UserImplentation', 'framework.auth.user.User')(두 번째 매개 변수는 기본값 일 수 있음). 그런 다음 프레임 워크의 사용자는 프레임 워크 User를 건드리지 않고 구현 을 대체 / 전문화 할 수 있습니다 .
tux21b

14
지나치게 단순화하고 대답하며 실제 생활에서는 "단일 톤"이 거의 필요하지 않으며 범위를 제어해야합니다 (스레드 로컬 단일 톤 또는 세션 단일 톤 등이 필요할 수 있음). 파이썬으로 해결 된 것은 실제로 기업 환경에서 해결 된 실제 문제가 아닙니다
Luxspes

3
실제로 DI는 코드의 종속성을 테스트하고 분리 할 수있게하는 것입니다. 또한 가져 오기 기능은 Java의 정적 가져 오기와 유사하므로 객체의 단일 인스턴스를 가져올 수 있습니다.
Richard Warburton

1
"모듈에서 가져 오기만하면 일종의"단일 "을 무료로 얻을 수 있습니다."정적 인스턴스 필드를 선언하고 값으로 설정하면 Java에서 쉽게 수행 할 수 있습니다. 이것은
혼자

45

IoC와 DI는 성숙한 파이썬 코드에서 매우 일반적입니다. 오리 타이핑 덕분에 DI를 구현하기 위해 프레임 워크가 필요하지 않습니다.

가장 좋은 예는 다음을 사용하여 Django 애플리케이션을 설정하는 방법입니다 settings.py.

# settings.py
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': REDIS_URL + '/1',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'snowflake',
    }
}

Django Rest Framework는 DI를 많이 활용합니다.

class FooView(APIView):
    # The "injected" dependencies:
    permission_classes = (IsAuthenticated, )
    throttle_classes = (ScopedRateThrottle, )
    parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
    renderer_classes = (renderers.JSONRenderer,)

    def get(self, request, *args, **kwargs):
        pass

    def post(self, request, *args, **kwargs):
        pass

알림 ( 출처 ) :

"종속성 주입"은 5 센트 개념의 25 달러 용어입니다. [...] 의존성 주입은 객체에 인스턴스 변수를 제공하는 것을 의미합니다. [...].


8
+1. 잘 넣어 파이썬 프로그래머이기 때문에 C #의 DI 프레임 워크에 대한 전체 인터뷰 프레젠테이션으로 완전히 당황했습니다. 프레임 워크가 필요 없기 때문에 Flask 앱에서 이미 생각조차하지 않고 이미 그것을 이미 알고 있음을 깨닫기 위해 잠시 시간을 들였습니다. C # / Java 이외의 것을 모르는 사람에게는 질문이 의미가 있습니다. 오리 형 언어 프로그래머에게는 자연스럽고 "5 센트 개념에 대한 25 달러 용어"입니다.
Samuel Harmer

5
err ... 인스턴스 ( IsAuthenticated, ScopedRateThrottle)가 클래스에 의해 인스턴스화 되므로 이는 종속성 주입이 아닙니다 . 생성자에 전달되지 않습니다.
dopatraman

5
IsAuthenticated그리고 ScopedRateThrottle인스턴스가 아니며 클래스입니다. FooView가 구성 될 때 (실제로 FooView가 요청을 처리 할 때) 인스턴스화됩니다. 어쨌든, 이것은 단지 구현 세부 사항입니다. IsAuthenticated그리고 ScopedRateThrottle의존성이다; 그들은 안으로 주입됩니다 FooView. 이 작업이 언제 또는 어떻게 수행 되는지 는 중요하지 않습니다 . 파이썬은 자바가 아니므로 이것을 구현하는 다른 방법이 있습니다.
Max Malysh

3
@MaxMalysh 나는 이것에 dopatraman에 동의합니다. 클래스 자체가 특정 클래스에 대한 "하드 코딩 된"종속성을 가지므로 IoC도 아닙니다. IoC에서, 의존성 shoudl은 하드 코딩 대신 제공됩니다. 또한 Dependency Injection에는 각 서비스의 수명주기를 관리하고 해당되는 경우 수명주기를 관리하는 엔티티가 있습니다. 해결책은 그 중 어느 것도 제공하지 않았습니다.
리카르도 알베스

3
@alex 아니요, 다른 렌더러를 사용하기 위해 코드를 변경할 필요가 없습니다. 여러 렌더러를 동시에 사용할 수도 있습니다 renderer_classes = (JSONRenderer, BrowsableAPIRenderer, XMLRenderer). 조롱은 간단합니다 @unittest.patch('myapp.views.FooView.permission_classes'). "무언가를 전달해야"하는 필사적 인 요구는 Java가 강력한 메타 프로그래밍 기능이 부족한 컴파일되고 정적으로 유형화 된 언어이기 때문에 "자바 작업 방식"의 결과입니다.
Max Malysh

35

Django는 제어 역전을 잘 활용합니다. 예를 들어, 구성 파일이 데이터베이스 서버를 선택한 다음 프레임 워크는 데이터베이스 클라이언트에 적절한 데이터베이스 랩퍼 인스턴스를 제공합니다.

차이점은 파이썬에는 일류 타입이 있다는 것입니다. 클래스를 포함한 데이터 유형 자체는 객체입니다. 특정 클래스를 사용하려는 경우 클래스 이름을 지정하십시오. 예를 들면 다음과 같습니다.

if config_dbms_name == 'postgresql':
    import psycopg
    self.database_interface = psycopg
elif config_dbms_name == 'mysql':
    ...

이후 코드는 다음을 작성하여 데이터베이스 인터페이스를 작성할 수 있습니다.

my_db_connection = self.database_interface()
# Do stuff with database.

Java 및 C ++에 필요한 상용구 팩토리 기능 대신 Python은 한두 줄의 일반 코드로이를 수행합니다. 이것이 기능적 프로그래밍 대 명령형 프로그래밍의 강점입니다.


4
코드라고 부르는 것은 실제로 배선 부분입니다. 이것이 ioc 프레임 워크의 XML입니다. 실제로 간단히 다음과 같이 쓸 수 있습니다 import psycopg2 as database_interface. 그 줄을 injections.pyet voilà 에 넣으십시오 .
스펙트럼

29
음. 당신이하는 일은 거의 교과서 명령형 다니엘입니다.
Shayne

반드시 필수 코드이지만 호출 가능 값을 값으로 사용하기 때문에 기능적입니다.
제레미

5
그래도 퍼스트 클래스 함수 아닌가요? en.wikipedia.org/wiki/First-class_function 그것들을 가지고 있고 사용한다고해서 코드가 기능하지는 않습니다. 여기서 발생하는 부작용 (예 : 변경 self.database_interface) 이 상당히 비명을 지르고 있습니다.
hjc1710

15

사람들은 의존성 주입과 제어 역전이 더 이상 의미하는 것을 실제로 얻지 못한다는 것을 알았습니다.

제어 반전을 사용하는 실습은 다른 클래스 또는 함수에 의존하는 클래스 또는 함수를 갖는 것이지만 함수 코드 클래스 대신 인스턴스를 작성하는 대신이를 매개 변수로 수신하는 것이 좋으므로 느슨한 결합을 달성 할 수 있습니다. 그것은 더 많은 테스트 가능성과 liskov 대체 원칙을 아카이빙하는 데 많은 이점이 있습니다.

인터페이스와 인젝션을 사용하면 코드를보다 지속 가능하게 만들 수 있습니다. 코드의 한 줄 (DI 구성에서 한 줄 또는 두 줄)을 다시 작성할 필요가 없기 때문에 동작을 쉽게 변경할 수 있기 때문입니다. 클래스가 기다리는 인터페이스를 구현하는 클래스는 인터페이스를 따르는 한 독립적으로 다를 수 있기 때문에 클래스의 동작을 변경하십시오. 코드를 분리하고 유지 관리하기 쉬운 최상의 전략 중 하나는 최소한 단일 책임, 대체 및 종속성 반전 원칙을 따르는 것입니다.

패키지 내에서 객체를 직접 인스턴스화하고 가져 와서 직접 주입 할 수있는 경우 DI 라이브러리가 무엇입니까? 자바에는 절차 적 섹션 (클래스 외부의 코드)이 없으므로 지루한 구성 xml에 들어가는 모든 것이 있으므로 지연로드 방식에 의존성을 인스턴스화하고 주입 해야하는 클래스가 필요하므로 날려 버리지 않습니다. 파이썬에서는 코드의 "절차"(클래스 외부 코드) 섹션에 주입을 코딩하기 만하면됩니다.


여전히 IoC / DI가 객체를 자동으로 연결한다는 사실을 그리워합니다. 런타임에 그렇게 할 수는 없지만 (자바는 리플렉션을 통해 수행 할 수 있음) 프레임 워크가 처리하므로 명시 적으로 수행 할 필요가 없습니다. 절차 적 섹션을 갖는 것도 중요하지 않으며, OOP 기능을 전혀 사용하지 않고 클래스를 정적 ​​서브 루틴 및 함수의 컨테이너로 사용하여 Java에서 전체 절차 적 앱을 작성하는 것을 막을 수있는 것은 없습니다.
zakmck

@zakmck : 파이썬의 "절차"섹션은 실제로 절차 코드 작성에 관한 것이 아닙니다. 파이썬의 "절차"섹션을 정적 언어와 다른 점은 클래스 정의 시간 동안 실행되는 클래스 본문에 절차 코드를 넣고 if 문에 import 문을 넣고 클래스를 정의하여 클래스 팩토리를 만드는 기능입니다. 공장 방법 내부. 정적 언어로는 실제로 할 수없는 일이며 IOC / DI가 해결하려고 시도한 대부분의 문제를 해결합니다. 파이썬에서 메타 프로그래밍은 보통 일반 파이썬 코드처럼 보입니다.
거짓말 라이언

@LieRyan, 리플렉션을 사용하여 수행하거나 자주 또는 런타임에 필요한 경우 Groovy (Java와 쉽게 재생할 수 있도록 설계된) 또는 Python 자체와 같은 다른 언어에서 정적 언어를 호출 할 수 있습니다. 그러나 IoC / DI 프레임 워크와는 거의 관련이 없습니다. 목적 상 대부분의 절차 적 객체 배선을 정의에만 활용하여 자동으로 수행합니다. 안타깝게도 대부분의 답변은이 점을 놓치게됩니다.
zakmck

12

몇 년 동안 파이썬을 사용하지는 않았지만 다른 언어보다 동적으로 유형이 지정된 언어와 관련이 있다고 말할 수 있습니다. 간단한 예를 들어, Java의 경우, 표준으로 작성된 것을 테스트하고 싶다면 DI를 사용하고 PrintStream을 전달하여 작성중인 텍스트를 캡처하고 확인할 수 있습니다. 그러나 Ruby에서 작업 할 때 STDOUT의 'puts'메소드를 동적으로 대체하여 확인을 수행하고 DI를 완전히 그림에서 제외시킵니다. 추상화를 생성하는 유일한 이유가 그것을 사용하는 클래스를 테스트하는 것 (파일 시스템 작업 또는 Java의 시계를 생각하는 것)이라면 DI / IoC는 솔루션에서 불필요한 복잡성을 만듭니다.


3
사람들이 시스템이 작동하는지 테스트하기 위해 시스템 작동 방식을 기꺼이 바꾸 겠다는 사실을 결코 놀라게하지 않습니다. 이제 테스트로 부작용이 발생하지 않는지 테스트해야합니다.
기본

2
그는 테스트 범위에서만 puts 메소드를 변경하는 것에 대해 이야기합니다. 주입 된 객체의 모의 메소드와 같습니다.
dpa

2
@Basic은 단위 테스트 에서 매우 정상적입니다 . 실제로 테스트 케이스 범위를 둘 이상의 코드 블록 (테스트중인 블록)으로 오염시키지 않으려면 이러한 테스트에서 수행하는 것이 좋습니다. 통합 테스트를 위해 그렇게하는 것은 잘못되었을 것입니다. 아마 당신의 의견에 대해 언급 한 것일까 요?
samuelgrigolato

1
저에게 테스트 가능성은 일류 관심사입니다. 디자인을 테스트 할 수없는 경우 디자인이 좋지 않으며 테스트 할 수 있도록 디자인을 변경하는 데 아무런 문제가 없습니다. 여전히 작동하는지 다시 확인해야하지만 괜찮습니다. 테스트 가능성은 코드 IMO를 변경해야하는 타당한 이유입니다.
Carlos Rodriguez

10

실제로 DI로 충분히 깨끗하고 컴팩트 한 코드를 작성하는 것은 매우 쉽습니다 (필자는 , 그때는 pythonic 일지 모르겠지만 어쨌든 :)).

def polite(name_str):
    return "dear " + name_str

def rude(name_str):
    return name_str + ", you, moron"

def greet(name_str, call=polite):
    print "Hello, " + call(name_str) + "!"

_

>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!

예, 이것은 함수 / 클래스를 매개 변수화하는 간단한 형태로 볼 수 있지만 작동합니다. 따라서 파이썬의 기본 포함 배터리로도 충분합니다.

추신 : 나는 또한 파이썬에서 간단한 부울 논리동적으로 평가할 때이 순진한 접근법의 더 큰 예를 게시했습니다 .


3
간단한 경우에는 효과가 있지만 다양한 모델 (Post, Comment, User)을 사용하는 간단한 웹 블로그 컨트롤러를 상상해보십시오. 사용자가 자신의 Post 모델 (추가 조회수 속성을 사용하여 추적 할 수 있음)과 더 많은 프로필 정보 등을 가진 사용자 모델을 주입하려는 경우 모든 매개 변수가 혼동 될 수 있습니다. 또한 사용자는 간단한 쿠키 기반 세션 또는 이와 유사한 것 대신 파일 시스템 세션을 지원하기 위해 Request 객체도 변경하려고 할 수 있습니다. 따라서 곧 많은 매개 변수가 생깁니다.
tux21b

1
@ tux21b 글쎄, 사용자가 애플리케이션을 구현하기를 원하는 "필수적인 복잡성"이 있으며, 이에 대한 아키텍처 솔루션이 있습니다 (일부 는 개발 및 유지 보수 시간, 실행 속도 등의 측면에서 나머지 솔루션 보다 나쁘지 않습니다 ). ) 및 API 및 소프트웨어 아키텍처를 이해할 수있는 인적 능력이 있습니다. DI를 사용하는 사람들뿐만 아니라 인간이 이해할 수있는 해결책이 없다면 ... 누가 모든 문제를 해결할 수 있다고 말했습니까? 그리고 기본적으로 할당 된 (그러나 사용자가 선택하여 바꿀 수있는) 매개 변수가 많으면 실제로 종종 충분할 수 있습니다.
mlvljr

9

IoC / DI는 디자인 컨셉이지만 불행히도 종종 특정 언어 (또는 타이핑 시스템)에 적용되는 컨셉으로 간주됩니다. 의존성 주입 컨테이너가 파이썬에서 훨씬 더 인기를 얻고 싶습니다. Spring이 있지만 그것은 슈퍼 프레임 워크이며 "The Python Way"에 대한 많은 고려없이 Java 개념의 직접적인 포트 인 것 같습니다.

파이썬 3의 주석을 감안할 때, 완전한 기능을 갖춘 간단한 의존성 주입 컨테이너 ( https://github.com/zsims/dic)에 균열이 생기기로 결정했습니다 . 그것은 .NET 의존성 주입 컨테이너 (IMO가 그 공간에서 놀고 있다면 환상적입니다)의 일부 개념을 기반으로하지만 Python 개념으로 변경되었습니다.


6

파이썬의 동적 특성으로 인해 사람들은 종종 다른 동적 프레임 워크가 필요하지 않다고 생각합니다. 클래스가 새로운 스타일의 '객체'에서 상속되면 새 변수를 동적으로 만들 수 있습니다 ( https://wiki.python.org/moin/NewClassVsClassicClass ).

일반 파이썬에서 :

#application.py
class Application(object):
    def __init__(self):
        pass

#main.py
Application.postgres_connection = PostgresConnection()

#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()

그러나 https://github.com/noodleflake/pyioc를 살펴보십시오. 이것은 당신이 찾고있는 것일 수 있습니다.

pyioc에서

from libs.service_locator import ServiceLocator

#main.py
ServiceLocator.register(PostgresConnection)

#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()

2
두 버전 모두 동일한 양의 코드를 사용한다는 사실은 왜 프레임 워크를 사용하는 것이 그리 인기가 없는지를 설명하는 데 큰 도움이됩니다.
스펙트럼

에서 other.py라인 (1), 자동 의존성 해상도가 있지만, 그래도 의존성 주입 그 계산하지 않을 것이다.
andho

서비스 로케이터는 일반적으로 반 패턴입니다.
PmanAce

6

"Jörg W Mittag"답변 : "DI / IoC의 Python 구현은 너무 가벼워서 완전히 사라졌습니다."

이 문장을 백업하려면 Java에서 Python으로 포팅 된 유명한 Martin Fowler의 예를 살펴보십시오. Python : Design_Patterns : Inversion_of_Control

위의 링크에서 볼 수 있듯이 파이썬의 "컨테이너"는 8 줄의 코드로 작성할 수 있습니다.

class Container:
    def __init__(self, system_data):
        for component_name, component_class, component_args in system_data:
            if type(component_class) == types.ClassType:
                args = [self.__dict__[arg] for arg in component_args]
                self.__dict__[component_name] = component_class(*args)
            else:
                self.__dict__[component_name] = component_class

42
이것은 가장 약한 DI 컨테이너조차도 훨씬 부족합니다. 수명 관리, 재귀 의존성 해결, 모의 능력 또는 구성에 실패한 기능은 어디에 있습니까? 이것은 IoC와 동일 하지 않은 유형 조회 및 캐시에 지나지 않습니다 .
기본

2
몇 년 전 저는 메타 클래스를 연습으로 사용하여 작은 DI 프레임 워크 를 작성했습니다 . 모든 것은 가져 오기 및 doctest가 0 인 단일 파일로, 자체 설명이 가능합니다. 기본 기능은 "pythonic"한 방식으로 구현하기가 어렵지 않지만 Spring에서 Java와 같이 완벽한 솔루션을 얻지 못하고 모든 사람이 사용자 정의 플러그인 아키텍처를 수행하는 것은 슬프다 고 생각합니다.
Andrea Ratto

2

내 2cents는 대부분의 Python 응용 프로그램에서 필요하지 않으며 필요한 경우에도 많은 Java 증오 자 (및 개발자라고 생각하는 무능한 피들러)가 Java에서 인기가 있기 때문에 나쁜 것으로 간주 할 가능성이 있습니다 .

IoC 시스템은 복잡한 객체 네트워크가있는 경우 실제로 유용합니다. 여기서 각 객체는 여러 다른 객체에 대한 종속성 일 수 있으며 결과적으로 자체가 다른 객체에 종속 될 수 있습니다. 이 경우 이러한 모든 개체를 한 번 정의하고 가능한 많은 암시 적 규칙에 따라 자동으로 구성 할 수있는 메커니즘이 필요합니다. 응용 프로그램 사용자 / 관리자가 간단한 방식으로 구성을 정의해야하는 경우, 이는 간단한 XML 파일 (구성이 될 수있는)에서 구성 요소를 읽을 수있는 IoC 시스템을 원하는 또 다른 이유입니다.

일반적인 Python 응용 프로그램은 복잡한 아키텍처없이 훨씬 간단하고 여러 스크립트 만 가능합니다. 개인적으로 나는 IoC가 실제로 무엇인지 알고 있습니다 (여기에서 특정 답변을 작성한 사람들과는 달리) 나는 제한된 Python 경험 (필자는 언제 어디서나 Spring을 사용하지 않습니다)에서 필요성을 느끼지 못했습니다. 개발 오버 헤드를 정당화하지는 않습니다.)

즉, IoC 접근 방식이 실제로 유용한 Python 상황이 있으며 실제로 Django가 그것을 사용한다는 것을 읽었습니다.

위와 같은 추론이 Java 세계의 Aspect Oriented Programming에 적용될 수 있지만 AOP가 실제로 가치가있는 경우의 수는 훨씬 제한적입니다.


django가 IoC를 사용하는 정보 소스에 대한 참조 URL이 있습니까?
Sajuuk

@Sajuuk, 나는이 질문의 스레드에서 Django에 대해 배웠으므로 모르겠습니다. 다른 답변 작성자에게 물어보십시오.
zakmck

이 답변의 첫 번째 행은 내 의견에 0 값을 추가합니다 ... 파이썬 코드가 IoC에서 이점을 얻을 수있는 시점을 결정할 수 있다고 생각하며 개발자가 나쁜 점을 생각하는 것은 신경 쓰지 않습니다. 나는 근거없는 의견보다는 실용주의를 소중히 여깁니다.
Mike de Klerk 2016 년

@MikedeKlerk 내 제안은 (많은 답변이 입증하는 바와 같이) 알려지지 않은 것과 선지자의 희생자가 아무리 객관적이고 잘 알려 졌음에도 불구하고 인기가 없을 것입니다. 물론 이것이 이것이 파이썬에서 많은 IoC 사용을 보지 못하는 이유인지 잘 모르겠습니다. 주된 이유는 저 / 중규모 compexity 앱이 필요하지 않다고 생각합니다.
zakmck

The typical Python application is much simpler, just a bunch of scripts, without such a complex architecture.-꽤 가정
hyankov


-1

파이썬에서 DI / IoC가 가능하고 쉽고 쉽고 아름답다는 점에서 @Jorg에 동의합니다. 누락 된 것은이를 지원하는 프레임 워크이지만 몇 가지 예외가 있습니다. 내 마음에 오는 몇 가지 예를 지적하려면 :

  • Django 주석을 사용하면 자신의 Comment 클래스를 사용자 지정 논리 및 양식에 연결할 수 있습니다. [더 많은 정보]

  • Django에서는 사용자 정의 프로파일 객체를 사용하여 사용자 모델에 연결할 수 있습니다. 이것은 완전히 IoC는 아니지만 좋은 접근 방법입니다. 개인적으로 주석 프레임 워크와 같이 구멍 사용자 모델을 바꾸고 싶습니다. [더 많은 정보]


-3

제 생각에 의존성 주입과 같은 것은 엄격하고 복잡한 프레임 워크의 증상입니다. 코드 본문이 쉽게 변경하기에 너무 무거워지면 코드의 작은 부분을 선택하고 인터페이스를 정의한 다음 해당 인터페이스에 연결된 객체를 통해 사람들이 동작을 변경할 수 있도록해야합니다. 그것은 모두 좋고 훌륭하지만 처음에는 그러한 종류의 복잡성을 피하는 것이 좋습니다.

정적 형식 언어의 증상이기도합니다. 추상화를 표현할 수있는 유일한 도구가 상속인 경우, 그것은 어디에서나 사용하는 것과 거의 같습니다. C ++은 매우 유사하지만 Java 개발자가 수행 한 모든 곳에서 빌더 및 인터페이스에 매료되지 않았습니다. 너무 많은 일반 코드를 작성하는 데 비용이 들지 않고 유연하고 확장 가능하다는 꿈을 가지고 과도한 부담을 느끼기 쉽습니다 . 문화적인 것 같아요.

일반적으로 파이썬 사람들은 작업에 적합한 도구를 선택하는 데 익숙하다고 생각합니다.이 도구는 일을 할 수 있지만 구성 순열의 어마 어마한 배열을 제공하는 하나의 진정한 도구 (천 가능한 플러그인 포함)가 아니라 일관되고 간단한 전체 도구입니다. . 필요한 경우 여전히 상호 교환 가능한 부분이 있지만, 오리 타이핑의 유연성과 언어의 상대적 단순성으로 인해 고정 인터페이스를 정의하는 큰 형식이 필요하지 않습니다.


4
언어 자체만큼 프레임 워크가 아닙니다. 덕 타이핑 언어가 누릴 수있는 유연성을 만들려면 정적 형식 언어에는 매우 정교한 프레임 워크와 규칙이 필요합니다. DI는 이러한 규칙 중 하나입니다. 파이썬 사람들은 두 번 생각하지 않습니다. 자바 사람들은 실제로 그 일을해야한다.
S.Lott

6
@ S.Lott-C ++ 사람들이 Java와 비슷한 제한 사항을 사용하면서도 디자인 및 아키텍처 패턴이 폭발하지 않는 것처럼 보이는 것을 제외하고는 전적으로 귀하에게 동의합니다. 나는이에 뭔가를 할 수있는 2 가지 방법에 직면하게되는 문화적 차이를 의미한다 생각, 자바 사람들의 C ++ 사람들 딥 바로 반면 전략 패턴을 용이하게하고 부울 및 if 문을 추가하는 또 다른 인터페이스를 추출하는 것을 선호 ...
Kylotan

3
@Finglas 그래서 내가 사용하는 12 개의 수업이 있고 EmailSender그것을으로 대체하기로 결정 DesktopNotifier했다면 12 개의 수업을 직접 편집해야합니다. 그리고 INotifier인터페이스에 작성 하고 컨테이너가 세부 사항을 처리하게 하는 것이 더 간단하고 깨끗하다고 ​​생각 하십니까?
기본

1
불행히도 특정 수준의 복잡성은 전문 소프트웨어 개발자가 직면해야하는 현실입니다. 이 답변에는 비판이 있지만 해결책은 없습니다. 이 문제에 대한 "pythonic"솔루션은 무엇입니까? 라이브러리를 작성 중이며 로깅을위한 후크 (PHP의 PSR-3 LoggerInterface와 같은 것)를 제공하려고합니다. 로그 수준을 사용하는 방법을 알고 있지만 프로그램에서 실제로보고하는 방법은 중요하지 않습니다. 클라이언트 앱이 해당 구현 세부 정보 를 주입 할 수있는 확실한 방법은 무엇입니까? 참고 : 응용 프로그램의 다른 부분에는이 인터페이스의 구현이 다를 수 있습니다.
Rob

2
당신에게 내 질문은 표준 로깅 라이브러리를 사용하는 방법이 아니며 로거 클래스의 다른 인스턴스를 만드는 것에 관한 것이 아닙니다. 내 질문은 응용 프로그램의 다른 부분이 다른 구현을 사용할 수 있고 세부 사항에 신경 쓰지 않도록 응용 프로그램을 구성하는 방법입니다 (인터페이스를 사용하는 방법을 알고 있다면). 이것은 내가 작업 한 여러 PHP 응용 프로그램에서 DI가 해결 한 매우 실제적인 문제입니다. 파이썬과 동등한 것을 찾고 있습니다. 그리고 "응용 프로그램을 복잡하게 만들지 마십시오"라는 제안은 내가 찾는 답이 아닙니다.
Rob

-5

Java의 강력한 유형과 달리. 파이썬의 오리 타이핑 동작은 객체를 쉽게 전달할 수있게합니다.

Java 개발자는 객체를 유연하게 유지하면서 클래스 구조와 객체 간의 관계를 구성하는 데 집중하고 있습니다. 이를 달성하기 위해서는 IoC가 매우 중요합니다.

파이썬 개발자는 작업 수행에 집중하고 있습니다. 필요할 때 수업을 연결하기 만하면됩니다. 그들은 수업의 종류에 대해 걱정할 필요조차 없습니다. qua 수있는 한 오리입니다! 이 자연은 IoC를위한 여지를 남기지 않습니다.


4
여전히 still 거리는 것을 찾아야합니다.
andho
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.