난 그냥 내 수업 중 하나를 간소화하려고하고 플라이급 디자인 패턴 과 같은 스타일로 몇 가지 기능을 도입했습니다 .
그러나 왜 __init__
항상 호출 된지에 대해 약간 혼란 스럽습니다 __new__
. 나는 이것을 기대하지 않았다. 왜 이런 일이 발생하는지, 그렇지 않으면 어떻게이 기능을 구현할 수 있는지 말해 줄 수 있습니까? (구현을 구현하는 __new__
것을 제외하고 는 상당히 해킹 된 느낌입니다.)
예를 들면 다음과 같습니다.
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
출력 :
NEW
INIT
EXISTS
INIT
EXISTS
INIT
왜?
답변
__new__
새 인스턴스 작성을 제어해야 할 때 사용하십시오 .
__init__
새 인스턴스의 초기화를 제어해야 할 때 사용하십시오
.
__new__
인스턴스 생성의 첫 단계입니다. 먼저 호출되며 클래스의 새 인스턴스를 반환합니다.반대로,
__init__
아무것도 반환하지 않습니다. 인스턴스를 만든 후에 만 초기화해야합니다.일반적으로
__new__
str, int, unicode 또는 tuple과 같은 불변 유형을 서브 클래스 화하지 않는 한 재정의 할 필요가 없습니다 .
2008년 4월 게시물에서 : 때 사용하는 __new__
대를 __init__
? mail.python.org에서.
당신이하려는 일이 일반적으로 팩토리로 이루어지며 그것이 최선의 방법 이라는 것을 고려해야 합니다. 사용 __new__
하는 것이 좋은 해결책은 아니므로 공장의 사용을 고려하십시오. 여기 좋은 공장 예가 있습니다.
답변
__new__
정적 클래스 메서드이고 __init__
인스턴스 메서드입니다.
__new__
인스턴스를 먼저 만들어야하므로 __init__
초기화 할 수 있습니다. 주 __init__
소요 self
매개 변수로. 인스턴스를 만들 때까지는 없습니다 self
.
이제 파이썬에서 싱글 톤 패턴 을 구현하려고 노력하고 있습니다. 몇 가지 방법이 있습니다.
또한 Python 2.6부터 클래스 데코레이터를 사용할 수 있습니다 .
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
@singleton
class MyClass:
...
답변
가장 잘 알려진 OO 언어에서와 같은 표현식 SomeClass(arg1, arg2)
은 새 인스턴스를 할당하고 인스턴스의 속성을 초기화 한 다음 반환합니다.
가장 잘 알려진 OO 언어에서 “인스턴스 속성 초기화”부분 은 기본적으로 새 인스턴스에서 작동하는 코드 블록 (생성자 표현식에 제공된 인수를 사용하여) 인 생성자 를 정의하여 각 클래스에 대해 사용자 정의 할 수 있습니다. )를 사용하여 원하는 초기 조건을 설정하십시오. 파이썬에서 이것은 클래스의 __init__
메소드에 해당합니다 .
파이썬 __new__
은 “새 인스턴스 할당”부분의 비슷한 클래스 별 사용자 정의에 지나지 않습니다. 물론 새 인스턴스를 할당하는 대신 기존 인스턴스를 반환하는 등의 비정상적인 작업을 수행 할 수 있습니다. 파이썬에서 우리는이 부분이 반드시 할당과 관련이 있다고 생각해서는 안됩니다. 우리가 필요로하는 것은 __new__
어딘가에서 적합한 인스턴스를 만들어 내는 것입니다.
그러나 그것은 여전히 작업의 절반에 불과하며, 파이썬 시스템이 때로는 작업의 다른 절반을 실행하고 싶을 때가 있다는 것을 알 __init__
수있는 방법이 없습니다. 당신이 그 행동을 원한다면, 당신은 그렇게 분명하게 말해야합니다.
종종 리팩토링하여 필요 __new__
하거나 필요하지 않거나 이미 초기화 된 객체에서 다르게 동작 __new__
하도록 할 수 __init__
있습니다. 당신이 정말로, 파이썬은 실제로 수 있습니까하려는 경우 그이 있도록하지만, “작업”을 다시 정의 할 SomeClass(arg1, arg2)
필요는 호출하지 않습니다 __new__
다음에 __init__
. 이렇게하려면 메타 클래스를 작성하고 해당 __call__
메소드를 정의해야 합니다.
메타 클래스는 클래스의 클래스 일뿐입니다. 그리고 클래스의 __call__
메소드는 클래스의 인스턴스를 호출 할 때 발생하는 일을 제어합니다. 따라서 metaclass ‘ __call__
메소드는 클래스를 호출 할 때 발생하는 상황을 제어합니다. 즉 , 인스턴스 생성 메커니즘을 처음부터 끝까지 재정의 할 수 있습니다 . 싱글 톤 패턴과 같은 완전히 비표준 인스턴스 생성 프로세스를 가장 우아하게 구현할 수있는 수준입니다. 사실, 코드의 10 개 라인 당신이 구현할 수있는 Singleton
다음도 futz에 당신을 필요로하지 않는 메타 클래스를 __new__
전혀 하고 설정할 수 있는 간단하게 추가하여 싱글로, 그렇지 않으면 정상 수업을 __metaclass__ = Singleton
!
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
그러나 이것은 아마도이 상황에서 보장되는 것보다 더 깊은 마법 일 것입니다!
답변
설명서 를 인용하려면 :
일반적인 구현에서는 적절한 인수와 함께 “super (currentclass, cls) .__ new __ (cls [, …])”를 사용하여 수퍼 클래스의 __new __ () 메서드를 호출 한 다음 필요에 따라 새로 만든 인스턴스를 수정하여 클래스의 새 인스턴스를 만듭니다. 그것을 반환하기 전에.
…
__new __ ()가 cls의 인스턴스를 반환하지 않으면 새 인스턴스의 __init __ () 메서드가 호출되지 않습니다.
__new __ ()는 주로 변경 불가능한 유형의 하위 클래스 (int, str 또는 tuple과 같은)가 인스턴스 작성을 사용자 정의 할 수 있도록하기위한 것입니다.
답변
이 질문은 상당히 오래되었지만 비슷한 문제가 있음을 알고 있습니다. 다음은 내가 원하는 것을했습니다.
class Agent(object):
_agents = dict()
def __new__(cls, *p):
number = p[0]
if not number in cls._agents:
cls._agents[number] = object.__new__(cls)
return cls._agents[number]
def __init__(self, number):
self.number = number
def __eq__(self, rhs):
return self.number == rhs.number
Agent("a") is Agent("a") == True
이 페이지를 리소스 http://infohost.nmt.edu/tcc/help/pubs/python/web/new-new-method.html 로 사용했습니다.
답변
이 질문에 대한 간단한 대답 __new__
은 클래스와 동일한 유형의 값을 반환하면 __init__
함수가 실행되고 그렇지 않으면 그렇지 않다는 것입니다. 이 경우 코드는와 A._dict('key')
동일한 클래스를 반환 cls
하므로 __init__
실행됩니다.
답변
__new__
같은 클래스의 인스턴스를 반환 하면 __init__
나중에 반환 된 객체에서 실행됩니다. 즉, 실행 __new__
을 막기 위해 사용할 수 없습니다 __init__
. 에서 이전에 생성 된 객체를 반환하더라도 반복 __new__
해서 두 번 초기화됩니다 (트리플 등) __init__
.
여기에 vartec 답변을 확장하고 수정하는 Singleton 패턴에 대한 일반적인 접근 방식이 있습니다.
def SingletonClass(cls):
class Single(cls):
__doc__ = cls.__doc__
_initialized = False
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Single, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self, *args, **kwargs):
if self._initialized:
return
super(Single, self).__init__(*args, **kwargs)
self.__class__._initialized = True # Its crucial to set this variable on the class!
return Single
전체 이야기는 여기에 있습니다 .
실제로 관련된 또 다른 접근법 __new__
은 클래스 메소드를 사용 하는 것 입니다.
class Singleton(object):
__initialized = False
def __new__(cls, *args, **kwargs):
if not cls.__initialized:
cls.__init__(*args, **kwargs)
cls.__initialized = True
return cls
class MyClass(Singleton):
@classmethod
def __init__(cls, x, y):
print "init is here"
@classmethod
def do(cls):
print "doing stuff"
이 방법을 @classmethod
사용하면의 실제 인스턴스를 사용하지 않으므로 모든 메소드를로 장식해야합니다 MyClass
.