__new__
을 호출하고 유형을 메타 클래스로 사용하는 경우 __new__
의 결과가 유형의 하위 유형 인 경우 __init__
이 호출됩니다. 다른 말로하면, Foo 클래스가 있다고 가정 해 봅시다. PyObject_Type(self)
의 결과를 호출하면 Foo()
과 동일합니다. 이것은 Foo를 의미합니다. __new__
이 호출되고 반환 값이 Foo의 하위 유형이면 __init__
이 호출됩니다.
Foo()를 호출하면 type_call (typeobject.c에서)이 실제로 호출되므로 tp_new 다음에 tp_init가옵니다. PyObject_Type (self) 대신 Foo_new()와 같이 객체의 새로운 기능을 직접 제공하면 __init__
을 호출하지 않고 __new__
을 호출하면 원하는 것을 얻을 수 있습니다. (Foo를 __new__
의 인수로 제공하는 것을 잊지 마십시오.)
마지막으로 질문에 대답 하시려면 Foo.__new__(Foo, ...)
으로 전화하십시오. 여기 당신이 찾고있는 것을 수행하는 코드가 있습니다. 나는이 모든 것을 알아 내려고 할 때 여담으로
class Foo(object):
def __new__(cls):
return super(Foo, cls).__new__(cls)
def __init__(self):
print "__init__"
def __reduce__(self):
return (Foo.__new__, (Foo,))
print "one"
x = Foo() # prints __init__
print "two"
y = Foo.__new__(Foo) # does not print __init__
print "three"
import pickle
p = pickle.dumps(Foo)
z = pickle.loads(p) # does not print __init__
은 거의 모든 경우에, 나는 사실 내 코드를 구현하고 __init__
호출 할 수있는 취약점이 발견했다. 내 오류는 __reduce__
튜플의 세 번째 인수로 들어가는 항목을 분리하지 않는다는 사실에서 비롯되었습니다. (__init__
에서 받아 들여지면) 두 번째 인수에 아무 것도 입력하지 않아도되며, 단지 __dict__
을 직접 업데이트하는 세 번째 인수에서 여러 가지를 제공하면됩니다. Modules and Objects 디렉토리에서 cpython 소스 코드를 살펴보면, __reduce__
의 구현을 볼 수 있습니다.
원칙적으로'__init__'는 호출되어서는 안되며, pickle이 선호하는 방법입니다. '__getinitargs__' 아래를보십시오 : "pickled 클래스 인스턴스가 unpickle되었을 때, 그것의'__init __()'메쏘드는 정상적으로 * 호출되지 않습니다." '__getinitargs__'를 구현하고 있습니까? –
좋아, 잊어 버려. 그것은 정상적인 수업에만 해당됩니다. –