f



Metaclasses - magic functions

Hi,

Quick question, can anybody tell me when to use __init__ instead of 
__new__ in meta programming?

I see that __new__ can be used mostly when I want to manipulate with 
class variables that are stored into dictionary.

But when to use __init__? Any example?

Thanx,
M
0
Mr
12/20/2016 9:04:40 PM
comp.lang.python 77058 articles. 3 followers. Post Follow

7 Replies
158 Views

Similar Articles

[PageSpeed] 45

On 12/20/2016 03:26 PM, Ian Kelly wrote:

> ... The latter is interesting mostly because it allows you to set the
> __slots__ or do something interesting with the __prepare__ hook
> (although the only interesting thing I've ever seen done with
> __prepare__ is to use an OrderedDict to preserve the the definition
> order of the class attributes; now that Python 3.6 does this by default
>  it's probably obsolete).

__prepare__ is not obsolete.  Enum uses it to set a custom dictionary which tracks the new members, etc.

--
~Ethan~
0
Ethan
12/20/2016 1:01:01 AM
On Tue, Dec 20, 2016 at 2:04 PM, Mr. Wrobel <mr@e-wrobel.pl> wrote:
> Hi,
>
> Quick question, can anybody tell me when to use __init__ instead of __new__
> in meta programming?
>
> I see that __new__ can be used mostly when I want to manipulate with class
> variables that are stored into dictionary.
>
> But when to use __init__? Any example?

__new__ is useful because of its power. You can use it to do things
like alter the name of the class or its base classes, or modify class
attributes before the class is created. The latter is interesting
mostly because it allows you to set the __slots__ or do something
interesting with the __prepare__ hook (although the only interesting
thing I've ever seen done with __prepare__ is to use an OrderedDict to
preserve the the definition order of the class attributes; now that
Python 3.6 does this by default it's probably obsolete).

__init__ is simpler than __new__. If you don't need to do any of the
fancy stuff above, you should probably use __init__ instead.

I can't think of any reason why one would ever want to use both on a metaclass.
0
Ian
12/20/2016 11:26:04 PM
"Mr. Wrobel" <mr@e-wrobel.pl> writes:

> Quick question, can anybody tell me when to use __init__ instead of
> __new__ in meta programming?

Use ‘__new__’ to do the work of *creating* one instance from nothing;
allocating the storage, determining the type, etc. — anything that will
be *the same* for every instance. ‘__new__’ is the constructor.

Use ‘__init__’ to do the work of *configuring* one instance, after it
already exists. Any attributes that are special to an instance should be
manipulated in the ‘__init__’ method. ‘__init__’ is the initialiser.

Because Python has a powerful type system built in, you generally have
little or nothing to do in ‘__new__’, and more work in ‘__init__’ for
each instance.


That's a general answer because you haven't said what your goal is. What
is it you want to do with types?

-- 
 \      “Fur coats made for the ladies from their own skin.” —furrier, |
  `\                                                            Sweden |
_o__)                                                                  |
Ben Finney

0
Ben
12/20/2016 11:39:33 PM
On 12/20/2016 03:39 PM, Ben Finney wrote:
> "Mr. Wrobel" writes:

>> Quick question, can anybody tell me when to use __init__ instead of
>> __new__ in meta programming?
>
> Use ‘__new__’ to do the work of *creating* one instance from nothing;
> allocating the storage, determining the type, etc. — anything that will
> be *the same* for every instance. ‘__new__’ is the constructor.
>
> Use ‘__init__’ to do the work of *configuring* one instance, after it
> already exists. Any attributes that are special to an instance should be
> manipulated in the ‘__init__’ method. ‘__init__’ is the initialiser.

That sounds like general object creation/class advice, which as a general
guideline is okay, but don't feel like it's the most important thing.

I only use `__new__` when the object being created is (or is based on)
an immutable type; otherwise I use `__init__`.  Likewise, if I'm using
`__new__` then I do all my configuration in `__new__` unless I have a
really good reason not to (such as making it easier for subclasses to
modify/skip `__init__`).

As far as metaclasses go... the only time I recall writing an `__init__`
for a metaclass was to strip off the extra arguments so `type.__init__`
wouldn't fail.

--
~Ethan~
0
Ethan
12/21/2016 1:51:15 AM
W dniu 21.12.2016 o 02:51, Ethan Furman pisze:
> On 12/20/2016 03:39 PM, Ben Finney wrote:
>> "Mr. Wrobel" writes:
>
>>> Quick question, can anybody tell me when to use __init__ instead of
>>> __new__ in meta programming?
>>
>> Use ‘__new__’ to do the work of *creating* one instance from nothing;
>> allocating the storage, determining the type, etc. — anything that will
>> be *the same* for every instance. ‘__new__’ is the constructor.
>>
>> Use ‘__init__’ to do the work of *configuring* one instance, after it
>> already exists. Any attributes that are special to an instance should be
>> manipulated in the ‘__init__’ method. ‘__init__’ is the initialiser.
>
> That sounds like general object creation/class advice, which as a general
> guideline is okay, but don't feel like it's the most important thing.
>
> I only use `__new__` when the object being created is (or is based on)
> an immutable type; otherwise I use `__init__`.  Likewise, if I'm using
> `__new__` then I do all my configuration in `__new__` unless I have a
> really good reason not to (such as making it easier for subclasses to
> modify/skip `__init__`).
>
> As far as metaclasses go... the only time I recall writing an `__init__`
> for a metaclass was to strip off the extra arguments so `type.__init__`
> wouldn't fail.
>
> --
> ~Ethan~
Hi,thanx for answers, let's imagine that we want to add one class 
attribute for newly created classess with using __init__ in metaclass, 
here's an example:

#!/usr/bin/env python

class MetaClass(type):
     # __init__ manipulation:

     def __init__(cls, name, bases, dct):
         dct['added_in_init'] = 'test'
         super(MetaClass, cls).__init__(name, bases, dct)

class BaseClass(object):
     __metaclass__ = MetaClass

class NewBaseClass(BaseClass):
     pass

print("Lets print attributes added in __init__ in base classes:")

print(BaseClass.added_in_init)

print(NewBaseClass.added_in_init)

after running it: AttributeError: type object 'BaseClass' has no 
attribute 'added_in_init'

Adding the same in __new__ works. Can anyone explain me please what's wrong?

Cheers,
M



0
Mr
12/23/2016 11:14:15 AM
On Fri, Dec 23, 2016 at 5:14 AM, Mr. Wrobel <mr@e-wrobel.pl> wrote:
> Hi,thanx for answers, let's imagine that we want to add one class attribute
> for newly created classess with using __init__ in metaclass, here's an
> example:
>
> #!/usr/bin/env python
>
> class MetaClass(type):
>     # __init__ manipulation:
>
>     def __init__(cls, name, bases, dct):
>         dct['added_in_init'] = 'test'
>         super(MetaClass, cls).__init__(name, bases, dct)
>
> class BaseClass(object):
>     __metaclass__ = MetaClass
>
> class NewBaseClass(BaseClass):
>     pass
>
> print("Lets print attributes added in __init__ in base classes:")
>
> print(BaseClass.added_in_init)
>
> print(NewBaseClass.added_in_init)
>
> after running it: AttributeError: type object 'BaseClass' has no attribute
> 'added_in_init'
>
> Adding the same in __new__ works. Can anyone explain me please what's wrong?

When __init__ is called, the class has already been constructed by
__new__, and the 'dct' argument has already been copied into the class
dict. The base __init__ method does nothing, so adding the item to dct
and calling up doesn't accomplish anything.

Instead, the 'cls' argument that gets passed into __init__ is the
newly constructed class, so just use that to set the attributes:

    cls.added_in_init = 'test'
0
Ian
12/23/2016 2:14:43 PM
W dniu 23.12.2016 o 15:14, Ian Kelly pisze:
(...)
>
>     cls.added_in_init = 'test'
>

Man, you are awsome genius! Finally somebody was able to explain me what 
is the power of __new__ and difference between __init__ !!!

So what I wanted to achieve was adding some new attributes to the class 
instances (objects) like this:

########
#!/usr/bin/env python

class MetaClass(type):
     # __init__ manipulation:

     def __init__(cls, name, bases, dct):
         cls.added_in_init = 'test'
         super(MetaClass, cls).__init__(name, bases, dct)

class BaseClass(object):
     __metaclass__ = MetaClass

class NewBaseClass(BaseClass):
     def __init__(self):
         self.inst_attr = self.added_in_init


print("Lets print attributes added in __init__ in base classes:")


b = NewBaseClass()
print(b.added_in_init)

print(b.inst_attr)
########

And finally it works!

Man I owe you a galaxy of thanks, because I was so frustrated! The 
examples taken from internet never explained me it in so clearly like 
you did!

Really, really thank you!!!
0
Mr
12/23/2016 7:20:41 PM
Reply: