2008-09-22 2 views
4

및 iCalendar 파일의 구문 분석 된 VEvent 객체를 기반으로 Calendar 객체를 만드는 Python 코드가 있습니다.어느 것이 모듈에서 함수로서의 팩토리인가, 생성하는 클래스의 메소드로서 어느 쪽이 더 파이썬인가?

캘린더 객체에는 파싱 된 이벤트를 추가하는 메소드 만 있습니다.

이제 파일 객체, 경로 또는 URL에서 캘린더를 만드는 팩토리 함수를 만들고 싶습니다.

I는 인스턴스 반환 직접 클래스에 클래스 메서드와 공장 기능을 구현하는 iCalendar python module, 사용하고있다 : 나는 자바에 대해 알고 작은 것과

cal = icalendar.Calendar.from_string(data) 

를, 이것은이다 자바 코드에서 일반적인 패턴을 사용하지만 실제로 인스턴스를 인스턴스화하려는 클래스와 다른 클래스에있는 팩토리 메소드에 대한 참조가 더 많이있는 것처럼 보입니다.

질문은 Pythonic으로 간주됩니까? 아니면 그냥 팩토리 함수로 모듈 수준의 메서드를 만드는 더 pythonic 간주됩니까?

답변

6

어딘가에서 읽은 일부 패턴의 밀교 차이를 생각하지 않고 공장 패턴처럼 어디서나 사용하고 싶습니다.

대부분의 경우 @staticmethod를 해결책으로 생각할 것입니다. 모듈 함수를 사용하는 것이 더 낫습니다. 하나의 모듈에 여러 클래스를 채우고 각기 다른 인터페이스를 구현하는 경우는 예외입니다. @staticmethod 사용하기

궁극적으로 @staticmethod 나 모듈 함수로 인스턴스를 생성하면 날씨에 별다른 차이가 없습니다.

파이썬에서 받아 들여지는 "패턴"중 하나가 클래스의 팩토리가 클래스 초기화라는 이유로 클래스의 이니셜 라이저 (__init__)를 사용했을 것입니다.

+0

Pythonista는 "muuuuu" –

+5

"나는 아마 ... 클래스의 초기화 ('__init__')를 사용하는 것"을 말한다 - 정말? 팩토리 메소드는 초기화가 아니라 생성/인스턴스화에 관한 메소드입니다. '__init__'가 호출 될 무렵에는 너무 늦었고, 객체는 만들어졌습니다. 어떤 클래스 생성자의 일부로 새로운 객체를 생성 할 때 영리한 팩토리 액션을하려고한다면'__init__'가 아니라'__new__'에 있어야합니다. – PaulMcG

0

공장 패턴은 자체 strengths and weaknesses입니다. 그러나 인스턴스를 작성하는 한 가지 방법을 선택하면 코드에 실용적인 효과가 거의 없습니다.

2

IMHO 모듈 수준 방법은 더 깨끗한 솔루션입니다. 파이썬 모듈 시스템 뒤에 숨겨져 고유 한 네임 스페이스 접두어를 붙이며 "공장 패턴"이 일반적으로 사용됩니다.

11

[참고. '캘린더'는 일정한 일정을 분리하고, '일정'은 일정에서 하나의 일정을 분리하는 데 매우주의해야합니다. 귀하의 질문에 약간의 혼란이있을 수 있습니다.]

공장 디자인 패턴에는 여러 가지 변형이 있습니다.

  1. 독립형 편의 기능 (예를 들어, calendarMaker (데이터)) 대상 클래스 (달력)를 구축

  2. 별도의 클래스 (예를 들어, CalendarParser).

  3. 클래스 수준 메서드 (예 : Calendar.from_string) 메서드입니다.

이들은 다른 용도로 사용됩니다.모두 Pythonic입니다. 질문은 "무엇이 당신입니까 입니까?" "무엇이 바뀔까?" 의미는 모든 것입니다. 변화가 중요합니다.

편의 기능은 Pythonic입니다. Java와 같은 언어는 부동 함수를 가질 수 없습니다. 당신은 클래스에서 외로운 함수를 감싸 야합니다. Python을 사용하면 클래스의 오버 헤드없이 외로운 함수를 사용할 수 있습니다. 함수는 생성자가 상태 변경이나 대체 전략 또는 이전 작업의 메모리가없는 경우 적합합니다.

때때로 사람들은 클래스를 정의한 다음 클래스의 인스턴스를 만들고 상태 및 전략 및 기타 구성에 대한 일반적인 매개 변수를 설정 한 다음 해당 클래스의 단일 관련 메서드를 호출하는 편의 함수를 제공합니다. 이것은 클래스의 statefulness와 독립 실행 형 함수의 유연성을 모두 제공합니다.

클래스 수준 메서드 패턴이 사용되지만 제한이 있습니다. 하나는 클래스 수준 변수에 의존해야한다는 것입니다. 이러한 것들은 혼란 스러울 수 있기 때문에, static 메소드로서의 복잡한 생성자는 (statefulness 나 alternative 전략과 같은) feature를 추가 할 필요가있을 때 문제가된다. 정적 메소드를 결코 확장하지 말라.

둘째, 나머지 클래스 메서드 및 특성과는 관계가 없습니다. 이 종류의 from_string은 Calendar 개체의 여러 가지 대체 인코딩 중 하나 일뿐입니다. from_xml, from_JSON, from_YAML 등이있을 수 있습니다. 이 중 아무 것도 캘린더의 의미와 관련성이 거의 없습니다. 이 메소드는 모두 캘린더가 전송을 위해 인코딩되는 방법에 관한 것입니다.

성숙한 파이썬 라이브러리에서 볼 수있는 것은 공장이 자신이 만든 것과 분리되어 있다는 것입니다. 인코딩 (문자열, XML, JSON, YAML 등)은 다소간의 무작위 변경의 영향을 많이받습니다. 그러나 본질적인 것은 거의 변하지 않습니다.

두 가지 문제를 구분하십시오. 인코딩 및 표현은 가능한 한 주 및 행동에서 멀리 유지하십시오.

0

staticmethod에는 거의 가치가 없지만 classmethod가 유용 할 수 있습니다. 그것은 당신이 클래스와 팩토리 함수가 실제로하고 싶은 것에 달려 있습니다.

모듈의 팩토리 함수는 항상 '올바른'유형의 인스턴스를 만듭니다 (귀하의 경우 '오른쪽'이 항상 '캘린더'클래스인데, 당신은 그것의 내용에 의존하게 만들 수도 있습니다 밖으로 인스턴스를 생성하고 있습니다.)

클래스 메소드는 데이터가 아니라 호출하는 클래스에서 종속되도록하려는 경우 사용하십시오. classmethod는 인스턴스없이 클래스에서 호출 할 수 있다는 점에서 staticmethod와 유사하지만 첫 번째 인수로 호출 된 클래스를 수신합니다. 이를 통해 원래 클래스의 서브 클래스 일 수있는 클래스의 인스턴스를 실제로 만들 수 있습니다. classmethod의 예는 dict.fromkeys()입니다.이 클래스는 키 목록과 단일 값 (기본값은 없음)으로 사전을 만듭니다. classmethod이기 때문에 하위 클래스 dict에서는 'fromkeys'메소드를 완전히 무료로 가져옵니다. . 여기에 하나가 dict.fromkeys을 쓸 수있는 방법의 예는 자신이()입니다 :

class dict_with_fromkeys(dict): 
    @classmethod 
    def fromkeys(cls, keys, value=None): 
     self = cls() 
     for key in keys: 
      self[key] = value 
     return self 
관련 문제