How to create a class instance without calling initializer? How to create a class instance without calling initializer? python python

How to create a class instance without calling initializer?


When feasible, letting __init__ get called (and make the call innocuous by suitable arguments) is preferable. However, should that require too much of a contortion, you do have an alternative, as long as you avoid the disastrous choice of using old-style classes (there is no good reason to use old-style classes in new code, and several good reasons not to)...:

   class String(object):      ...   bare_s = String.__new__(String)

This idiom is generally used in classmethods which are meant to work as "alternative constructors", so you'll usually see it used in ways such as...:

@classmethod def makeit(cls):    self = cls.__new__(cls)    # etc etc, then    return self

(this way the classmethod will properly be inherited and generate subclass instances when called on a subclass rather than on the base class).


A trick the standard pickle and copy modules use is to create an empty class, instantiate the object using that, and then assign that instance's __class__ to the "real" class. e.g.

>>> class MyClass(object):...     init = False...     def __init__(self):...         print 'init called!'...         self.init = True...     def hello(self):...         print 'hello world!'... >>> class Empty(object):...     pass... >>> a = MyClass()init called!>>> a.hello()hello world!>>> print a.initTrue>>> b = Empty()>>> b.__class__ = MyClass>>> b.hello()hello world!>>> print b.initFalse

But note, this approach is very rarely necessary. Bypassing the __init__ can have some unexpected side effects, especially if you're not familiar with the original class, so make sure you know what you're doing.


Using a metaclass provides a nice solution in this example. The metaclass has limited use but works fine.

>>> class MetaInit(type):    def __call__(cls, *args, **kwargs):        if args or kwargs:            return super().__call__(*args, **kwargs)        return cls.__new__(cls)>>> class String(metaclass=MetaInit):    def __init__(self, string):        self.__string = tuple(string.split())        self.__simple = tuple(self.__simple())    def __simple(self):        letter = lambda s: ''.join(filter(lambda s: 'a' <= s <= 'z', s))        return filter(bool, map(letter, map(str.lower, self.__string)))    def __eq__(self, other):        assert isinstance(other, String)        return self.__simple == other.__simple    def __getitem__(self, key):        assert isinstance(key, slice)        string = String()        string.__string = self.__string[key]        string.__simple = self.__simple[key]        return string    def __iter__(self):        return iter(self.__string)>>> String('Hello, world!')[1:]<__main__.String object at 0x02E78830>>>> _._String__string, _._String__simple(('world!',), ('world',))>>> 

Addendum:

After six years, my opinion favors Alex Martelli's answer more than my own approach. With meta-classes still on the mind, the following answer shows how the problem can be solved both with and without them:

#! /usr/bin/env python3METHOD = 'metaclass'class NoInitMeta(type):    def new(cls):        return cls.__new__(cls)class String(metaclass=NoInitMeta if METHOD == 'metaclass' else type):    def __init__(self, value):        self.__value = tuple(value.split())        self.__alpha = tuple(filter(None, (            ''.join(c for c in word.casefold() if 'a' <= c <= 'z') for word in            self.__value)))    def __str__(self):        return ' '.join(self.__value)    def __eq__(self, other):        if not isinstance(other, type(self)):            return NotImplemented        return self.__alpha == other.__alpha    if METHOD == 'metaclass':        def __getitem__(self, key):            if not isinstance(key, slice):                raise NotImplementedError            instance = type(self).new()            instance.__value = self.__value[key]            instance.__alpha = self.__alpha[key]            return instance    elif METHOD == 'classmethod':        def __getitem__(self, key):            if not isinstance(key, slice):                raise NotImplementedError            instance = self.new()            instance.__value = self.__value[key]            instance.__alpha = self.__alpha[key]            return instance        @classmethod        def new(cls):            return cls.__new__(cls)    elif METHOD == 'inline':        def __getitem__(self, key):            if not isinstance(key, slice):                raise NotImplementedError            cls = type(self)            instance = cls.__new__(cls)            instance.__value = self.__value[key]            instance.__alpha = self.__alpha[key]            return instance    else:        raise ValueError('METHOD did not have an appropriate value')    def __iter__(self):        return iter(self.__value)def main():    x = String('Hello, world!')    y = x[1:]    print(y)if __name__ == '__main__':    main()