Python uNew_u uInit_u uCall_uDetailed

Posted by weknowtheworld on Fri, 03 Jul 2020 16:41:30 +0200

new

  • __new__(cls, *args, **kwargs)
  • Create an instance (usually cls or other types of instances)

init

  • __init__(self, *args, **Kwargs)
  • After the instance is created by new, it is executed before being returned to the caller

  • If new returns an instance of cls, the init method is automatically executed, self is the instance created, and the init and new parameters are the same

    If new() returns an instance of cls, then the new instance's init() method will be invoked like init(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to new().

  • If new does not return an instance of cls, the init method will not be executed

    If new() does not return an instance of cls, then the new instance's init() method will not be invoked.

  • new is used to inherit immutable types and create custom instances; it can also be used to override custom metaclasses and create custom instances

    new() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

call

  • __call__(self, *args, **Kwargs)
  • Trigger when the created instance is called; take a chestnut, instance, and execute instance() to trigger call
  • That is, an instance of a class is allowed to be called like a function

Sample Code

  • new returns an instance of the class itself
class Bar(object):
    pass
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        return super(Foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
foo(1, 2, 3, other=['a', 'b'])

foo new
args ('a', 1)
kwargs {'other': ['id', 'ip']}
foo init
args ('a', 1)
kwargs {'other': ['id', 'ip']}
foo call
args (1, 2, 3)
kwargs {'other': ['a', 'b']}

  • new does not return an instance (init will not be executed, call will error if called)
# coding: utf-8
class Bar(object):
    pass
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        # return super(Foo, cls).__new__(cls, *args, **kwargs)
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
# foo(1, 2, 3, other=['a', 'b']) # NonType object is not callable

foo new
args ('a', 1)
kwargs {'other': ['id', 'ip']}

  • new returns another type of instance (init will not be executed, call calls the returned instance)
# coding: utf-8
class Bar(object):
    def __call__(self, *args, **kwargs):
        print 'bar call'
class Foo(object):
    def __new__(cls, *args, **kwargs):
        print 'foo new'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
        return Bar()
    def __init__(self, *args, **kwargs):
        print 'foo init'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
    def __call__(self, *args, **kwargs):
        print 'foo call'
        print 'args {}'.format(args)
        print 'kwargs {}'.format(kwargs)
foo = Foo('a', 1, other=['id', 'ip'])
foo(1, 2, 3, other=['a', 'b'])

foo new
args ('a', 1)
kwargs {'other': ['id', 'ip']}
bar call

  • Difference between new and init when inheriting immutable types
# coding: utf-8
class Foo(int):
    def __init__(self, *args, **kwargs):
        super(Foo, self).__init__(100)
foo = Foo(1)
# Cannot be modified in init
print foo

1

# coding: utf-8
class Foo(int):
    def __new__(cls, *args, **kwargs):
        return super(Foo, cls).__new__(cls, 100)
foo = Foo(1)
# Can be modified in new
print foo

100

  • Use of new in metaclass programming (metaprogramming related, then written separately)
# coding: utf-8
class Foo(type):
    def __new__(cls, *args, **kwargs):
        ret = super(Foo, cls).__new__(cls, *args, **kwargs)
        return ret
class Bar():
    __metaclass__ = Foo
bar = Bar()
print bar

Topics: Programming