рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╡рд░реНрдЧ рдлреВ рд╣реИ :
class Foo(object): def __init__(self, x, y=0): self.x = x self.y = y
рдЬрдм рдЖрдк рдЗрд╕рдХреА рд╡рд╕реНрддреБ рдмрдирд╛рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ?
f = Foo(1, y=2)
рдлреВ рдХреЛ рдЗрд╕ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХрд┐рд╕ рд╡рд┐рдзрд┐ рдХреЛ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ? рдЕрдзрд┐рдХрд╛рдВрд╢ рдирд╡рд╛рдЧрдВрддреБрдХреЛрдВ, рдФрд░ рд╢рд╛рдпрдж рдХреБрдЫ рдЕрдиреБрднрд╡реА pythonists, рддреБрд░рдВрдд рдЬрд╡рд╛рдм рджреЗрдВрдЧреЗ: " __in____ рд╡рд┐рдзрд┐ред" рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдКрдкрд░ рдХреЗ рд╕реНрдирд┐рдкреЗрдЯреНрд╕ рдХреЛ рдХрд░реАрдм рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЬрд▓реНрдж рд╣реА рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдРрд╕рд╛ рдЙрддреНрддрд░ рдЧрд▓рдд рд╣реИред
__init__ рдХреЛрдИ рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдлреВ (1, y = 2) , рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИ ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, __init__ рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реНрд╡рдпрдВ рдХреЛ рд▓реЗрддрд╛ рд╣реИ, рдЬреЛ рдлреВ (1, y = 2) рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣рдо рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗред
рдСрдмреНрдЬреЗрдХреНрдЯ рдХреНрд░рд┐рдПрд╢рди рдкреНрд░реЛрд╕реАрдЬрд░
рдкрд╛рдпрдерди рддрд╛рддреНрдХрд╛рд▓рд┐рдХрддрд╛ рдореЗрдВ рдХрдИ рдЪрд░рдг рд╣реЛрддреЗ рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рдг рдХреЛ рд╕рдордЭрдирд╛ рд╣рдореЗрдВ рднрд╛рд╖рд╛ рдХреЛ рд╕рдордЧреНрд░ рд░реВрдк рд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдирд┐рдХрдЯ рдмрдирд╛рддрд╛ рд╣реИред рдлреВ рдПрдХ рд╡рд░реНрдЧ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд╛рдпрдерди рдореЗрдВ, рдХрдХреНрд╖рд╛рдПрдВ рднреА рд╡рд╕реНрддреБрдПрдВ рд╣реИрдВ! рдХрдХреНрд╖рд╛рдПрдВ, рдлрд╝рдВрдХреНрд╢рдВрд╕, рд╡рд┐рдзрд┐рдпрд╛рдБ рдФрд░ рдЙрджрд╛рд╣рд░рдг рд╕рднреА рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИрдВ, рдФрд░ рдЬрдм рднреА рдЖрдк рдЙрдирдХреЗ рдирд╛рдо рдХреЗ рдмрд╛рдж рдХреЛрд╖реНрдардХ рд▓рдЧрд╛рддреЗ рд╣реИрдВ , рддреЛ рдЖрдк рдЙрдирдХреА __call__ рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВред рддреЛ Foo (1, y = 2) Foo .__ рдХреЙрд▓ __ (1, y = 2) рдХреЗ рд╕рдорддреБрд▓реНрдп рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, __call__ рд╡рд┐рдзрд┐ рдлреВ рд╡рд╕реНрддреБ рдХреЗ рд╡рд░реНрдЧ рдореЗрдВ рдШреЛрд╖рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИред рдлреВ рд╡рд╕реНрддреБ рдХрд╛ рд╡рд░реНрдЧ рдХреНрдпрд╛ рд╣реИ?
>>> Foo.__class__ <class 'type'>
рддреЛ Foo рд╡рд░реНрдЧ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдХрдХреНрд╖рд╛ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдФрд░ рдЕрдВрддрд┐рдо рд╡рд░реНрдЧ рдХреЗ __call__ рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ Foo рд╡рд░реНрдЧ рдХреЛ рджреЗрддрд╛ рд╣реИред рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЯрд╛рдЗрдк рдХреНрд▓рд╛рд╕ рдХрд╛ __call__ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИред рдиреАрдЪреЗ C рдореЗрдВ CPython рдореЗрдВ рдФрд░ PyPy рдореЗрдВ рдЗрд╕рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЙрдиреНрд╣реЗрдВ рджреЗрдЦрдХрд░ рдердХ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рдФрд░ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдВ:
CPython
рд╕реНрд░реЛрдд рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВ
static PyObject * type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *obj; if (type->tp_new == NULL) { PyErr_Format(PyExc_TypeError, "cannot create '%.100s' instances", type->tp_name); return NULL; } obj = type->tp_new(type, args, kwds); obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL); if (obj == NULL) return NULL; if (type == &PyType_Type && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) return obj; if (!PyType_IsSubtype(Py_TYPE(obj), type)) return obj; type = Py_TYPE(obj); if (type->tp_init != NULL) { int res = type->tp_init(obj, args, kwds); if (res < 0) { assert(PyErr_Occurred()); Py_DECREF(obj); obj = NULL; } else { assert(!PyErr_Occurred()); } } return obj; }
PyPy
рд╕реНрд░реЛрдд рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВ
def descr_call(self, space, __args__): promote(self)
рдпрджрд┐ рдЖрдк рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рдЬрд╛рдВрдЪ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рднреВрд▓ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рд▓рдЧрднрдЧ рдЗрд╕рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИрдВ:
def __call__(obj_type, *args, **kwargs): obj = obj_type.__new__(*args, **kwargs) if obj is not None and issubclass(obj, obj_type): obj.__init__(*args, **kwargs) return obj
__new__ "рдЦрд╛рд▓реА" рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП __init__ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ:
- Foo (* args, ** kwargs) Foo .__ рдХреЙрд▓ __ (* args, ** kwargs) рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИред
- рдЪреВрдВрдХрд┐ рдлреВ рдСрдмреНрдЬреЗрдХреНрдЯ рдЯрд╛рдЗрдк рдХреНрд▓рд╛рд╕ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдлреВ .__ рдХреЙрд▓ __ (* рдЖрд░реНрдЧреНрд╕, ** рдХрд╡рд░реНрд╕) рдЯрд╛рдЗрдк рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ ред__ рдХреЙрд▓ __ (рдлреВ, рдЕрд░реНрдЧреНрд╕, ** рдХрд╡рд░реНрд╕) ред
- рдкреНрд░рдХрд╛рд░ .__ рдХреЙрд▓ __ (рдлреВ, * рдЖрд░реНрдЧреНрд╕, ** рдХрд╡рд░реНрд╕) рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВ ред__ рдирдИ __ (рдлреВ, * рдЖрд░реНрдЧреНрд╕, ** рдХрд╡рд░реНрд╕) рд╡рд┐рдзрд┐, рдЬреЛ рдУрдмреНрдЬ рд░рд┐рдЯрд░реНрди рдХрд░рддреА рд╣реИред
- obj рдХреЛ obj .__ init __ (* args, ** kwargs) рдХрд╣рдХрд░ рдЖрд░рдореНрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдкреВрд░реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдПрдХ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдУрдмреНрдЬреЗрдХреНрдЯ рд╣реИ ред
рдЕрдиреБрдХреВрд▓рди
рдЕрдм рд╣рдо __new__ рдХреА рдУрд░ рдЕрдкрдирд╛ рдзреНрдпрд╛рди рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╡рд┐рдзрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддреА рд╣реИ рдФрд░ рдЙрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рддреА рд╣реИред рдЖрдк рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рд╣реИрдВред рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрджреНрдпрдкрд┐ __new__ рдПрдХ рд╕реНрдерд┐рд░ рд╡рд┐рдзрд┐ рд╣реИ, рдЖрдкрдХреЛ @staticmethod рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ: рджреБрднрд╛рд╖рд┐рдпрд╛ __new__ рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддрд╛ рд╣реИред
__New__ рдУрд╡рд░рд░рд╛рдЗрдбреНрд╕ рдХрд╛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЙрджрд╛рд╣рд░рдг рд╕рд┐рдВрдЧрд▓рдЯрди рдмрдирд╛ рд░рд╣рд╛ рд╣реИ:
class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance
рддрдм:
>>> s1 = Singleton() ... s2 = Singleton() ... s1 is s2 True
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ __in__ рдХреЛ рд╣рд░ рдмрд╛рд░ рд╕рд┐рдВрдЧрд▓рдЯрди () рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рджреЗрдЦрднрд╛рд▓ рдХреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдПред
__New__ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд╛ рдПрдХ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдмреЛрд░реНрдЧ рдкреИрдЯрд░реНрди ("рдмреЛрд░реНрдЧ") рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:
class Borg(object): _dict = None def __new__(cls, *args, **kwargs): obj = super().__new__(cls, *args, **kwargs) if cls._dict is None: cls._dict = obj.__dict__ else: obj.__dict__ = cls._dict return obj
рддрдм:
>>> b1 = Borg() ... b2 = Borg() ... b1 is b2 False >>> b1.x = 8 ... b2.x 8
рдзреНрдпрд╛рди рд░рдЦреЗрдВ рдХрд┐ рд╣рд╛рд▓рд╛рдВрдХрд┐ рдКрдкрд░ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг __new__ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛рдУрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:
__new__ рджреБрд░реБрдкрдпреЛрдЧ рдХреА рд╕рдмрд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рд╢рд┐рдХрд╛рд░ рд▓реЛрдЧреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдХреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рд╕реЗ рдмреЗрд╣рддрд░ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬрдм рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рддреЛ __new__ рдПрдХ рдЕрддреНрдпрдВрдд рдЙрдкрдпреЛрдЧреА рдФрд░ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реИред
- рдкрд╛рдЗрдерди рдореЗрдВ рдПрд░рд┐рдпрди рд╕реНрдкреИрдЧ, рдж рд╡реЗрд▓ рдлреЙрд░рдЧреЙрдЯреЗрди рдУрд▓реНрдб
рдПрдХ рд╢рд╛рдпрдж рд╣реА рдХрднреА рдкрд╛рдпрдерди рдореЗрдВ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди __new__ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдерд╛ ред рд▓реЗрдХрд┐рди рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рд╣рдереМрдбрд╝рд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рд░ рд╕рдорд╕реНрдпрд╛ рдирд╛рдЦреВрди рдХреА рддрд░рд╣ рджрд┐рдЦрдирд╛ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рдПрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░реЗрдВ ред