[BangPypers] returning value from a class

Sidu Ponnappa lorddaemon at gmail.com
Wed Apr 6 15:34:23 CEST 2011


> Why do you want to create a class that doesn't create itself when called?
It's interesting this came up today - we were just arguing about this at
work on Monday. Some of my colleagues are of the opinion that this is a Bad
Thing and should never be done. I agree that while it's a bad thing, there
are rare occasions where it's still the most elegant solution. After all,
the allocator is just a factory - I don't see why it should be treated as
something special. As long as you have some rules (like the rules for
overriding the default equality method in any OO language) you should be
fine.

FWIW, these are my two rules:
* Don't do it unless there's no other sensible option. Like, absolutely
nothing else exists that is more elegant.
* Ensure that you're returning a sub-class of the class where you're
implementing a custom allocator. No returning a different type, and
definitely no returning a nil.

Here's one occasion where I had call to do this. See

https://github.com/kaiwren/wrest/blob/master/spec/wrest/native/response_spec.rb#L41

for the spec and

https://github.com/kaiwren/wrest/blob/master/lib/wrest/native/response.rb#L43

for the code. It's in Ruby, though.

Best,
Sidu.
http://c42.in
http://about.me/ponnappa

On Wed, Apr 6, 2011 at 6:41 PM, Noufal Ibrahim <noufal at gmail.com> wrote:

>
> You're opening up can of worms here but I'll try to sort it out since
> I'm feeling messed up anyway.
>
> First : Old style and new style classes
> ---------------------------------------
> "class X:" in Python 2.x creates an old style class[1]
>
> These classes were distinct from builtin "type"s. All such classes were
> of type "classobj" and instances would be of type "instance".
>
> "class X(object):" in Python 2.x creates a new style class[1]
>
> for which the class is of type 'type' which is ultimately the root of
> for all the builtin types as well. Instances would have the class as
> their type. So if you do
>
>   x = X()
>
> and then ask for the type of X, you'd get "class X" for new style and
> "instance" for old style.
>
> With Python 3, the old style class was dropped and no longer
> supported. A plain class declaration would create a new style class.
>
> In your example, the 2.x variant is using an old style class and the 3.x
> one a new style class. Replacing your 2.x definition with
>
>   class x(object):
>
> will create a new style class that will work in the same way as with
> Python 3.
>
> Second : The __new__ and __init__ methods
> -----------------------------------------
>
> The __new__ method is an allocator. It "creates" the object. The
> __init__ method is an "initialiser" and might not always be called
> (e.g. while depickling). It will initialise the object created.
>
> Python semantics[2] state that if your __new__ method returns an object
> of a type different from the class it's allocating, the __init__ method
> will not be called. That's what's happening in your situation.
>
> Now, why is this not happening for old style classes? Well, I need to
> dig into the source to confirm this but one of the things that was added
> when they moved to new style classes (after 2.1 I think) is hooks that
> allow overriding of the allocation process. This made metaclasses and
> all that possible. This is not the case with old style classes where the
> allocator was not even exposed.
>
>
> >>> class F:
> ...   def __new__(cls):
> ...     print "Hello"
> ...     return 5
> ...
> >>> F()
> <__main__.F instance at 0x7fa759a4e908>
> >>>
>
>
> will not even print the "Hello" since there was no __new__.
>
> Thirdly : What are you trying to do?
> ------------------------------------
>
> Why do you want to create a class that doesn't create itself when
> called? I'm not chastising you but most situations where this kind of
> thing is done are interesting and I'm curious to know more.
>
>
> On Wed, Apr 06 2011, Nitin Kumar wrote:
>
> > Hi All,
> >
> > I am looking for a return value when an object is created.
> > but can see different behavior in different python version.
> >
> > Python 3 gives
> >>>> class x:
> > def __new__(self):
> > return 5
> >
> >>>> x()
> > 5
> >
> >
> > Python 2.6.5 gives
> >>>> class x:
> > def __new__(self):
> > return 5
> >
> >>>> x()
> > <__main__.x instance at 0x017CFD00>
> >
> > I need to use 2.6 only, so how to achieve the same functionality as in
> > python 3.
>
>
> Footnotes:
> [1]  http://docs.python.org/release/2.5.2/ref/node33.html
>
> [2]  http://docs.python.org/reference/datamodel.html#object.__new__
>
> --
> _______________________________________________
> BangPypers mailing list
> BangPypers at python.org
> http://mail.python.org/mailman/listinfo/bangpypers
>


More information about the BangPypers mailing list