[Python-Dev] Python 3, new-style classes and __class__

Guido van Rossum guido at python.org
Sun Nov 20 17:35:26 CET 2011


Um, what?! __class__ *already* has a special meaning. Those examples
violate that meaning. No wonder they get garbage results.

The correct way to override isinstance is explained here:
http://www.python.org/dev/peps/pep-3119/#overloading-isinstance-and-issubclass
.

--Guido

On Sat, Nov 19, 2011 at 6:13 PM, Michael Foord
<fuzzyman at voidspace.org.uk> wrote:
>
>
> On 19 November 2011 23:11, Vinay Sajip <vinay_sajip at yahoo.co.uk> wrote:
>>
>> Michael Foord <fuzzyman <at> voidspace.org.uk> writes:
>>
>> > That works fine in Python 3 (mock.Mock does it):
>> >
>> >  >>> class Foo(object):
>> > ...  @property
>> > ...  def __class__(self):
>> > ...   return int
>> > ...
>> >  >>> a = Foo()
>> >  >>> isinstance(a, int)
>> > True
>> >  >>> a.__class__
>> > <class 'int'>
>> >
>> > There must be something else going on here.
>> >
>>
>> Michael, thanks for the quick response. Okay, I'll dig in a bit further:
>> the
>> definition in SimpleLazyObject is
>>
>> __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
>>
>> so perhaps the problem is something related to the specifics of the
>> definition.
>> Here's what I found in initial exploration:
>>
>> --------------------------------------------------------------------------
>> Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
>> [GCC 4.6.1] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>> >>> from django.utils.functional import SimpleLazyObject
>> >>> fake_bool = SimpleLazyObject(lambda: True)
>> >>> fake_bool.__class__
>> <type 'bool'>
>> >>> fake_bool.__dict__
>> {'_setupfunc': <function <lambda> at 0xca9ed8>, '_wrapped': True}
>> >>> SimpleLazyObject.__dict__
>> dict_proxy({
>>    '__module__': 'django.utils.functional',
>>    '__nonzero__': <function inner at 0xca9de8>,
>>    '__deepcopy__': <function __deepcopy__ at 0xca9c08>,
>>    '__str__': <function inner at 0xca9b18>,
>>    '_setup': <function _setup at 0xca9aa0>,
>>    '__class__': <property object at 0xca5730>,
>>    '__hash__': <function inner at 0xca9d70>,
>>    '__unicode__': <function inner at 0xca9b90>,
>>    '__bool__': <function inner at 0xca9de8>,
>>    '__eq__': <function inner at 0xca9cf8>,
>>    '__doc__': '\n A lazy object initialised from any function.\n\n
>>        Designed for compound objects of unknown type. For builtins or
>>        objects of\n known type, use django.utils.functional.lazy.\n ',
>>    '__init__': <function __init__ at 0xca9a28>
>> })
>> --------------------------------------------------------------------------
>> Python 3.2.2 (default, Sep 5 2011, 21:17:14)
>> [GCC 4.6.1] on linux2
>> Type "help", "copyright", "credits" or "license" for more information.
>> >>> from django.utils.functional import SimpleLazyObject
>> >>> fake_bool = SimpleLazyObject(lambda : True)
>> >>> fake_bool.__class__
>> <class 'django.utils.functional.SimpleLazyObject'>
>> >>> fake_bool.__dict__
>> {
>>    '_setupfunc': <function <lambda> at 0x1c36ea8>,
>>    '_wrapped': <object object at 0x1d88b70>
>> }
>> >>> SimpleLazyObject.__dict__
>> dict_proxy({
>>    '__module__': 'django.utils.functional',
>>    '__nonzero__': <function inner at 0x1f56490>,
>>    '__deepcopy__': <function __deepcopy__ at 0x1f562f8>,
>>    '__str__': <function inner at 0x1f561e8>,
>>    '_setup': <function _setup at 0x1f56160>,
>>    '__hash__': <function inner at 0x1f56408>,
>>    '__unicode__': <function inner at 0x1f56270>,
>>    '__bool__': <function inner at 0x1f56490>,
>>    '__eq__': <function inner at 0x1f56380>,
>>    '__doc__': '\n A lazy object initialised from any function.\n\n
>>        Designed for compound objects of unknown type. For builtins or
>>        objects of\n known type, use django.utils.functional.lazy.\n ',
>>    '__init__': <function __init__ at 0x1f560d8>
>> })
>> --------------------------------------------------------------------------
>>
>> In Python 3, there's no __class__ property as there is in Python 2,
>> the fake_bool's type isn't bool, and the callable to set up the wrapped
>> object never gets called (which is why _wrapped is not set to True, but to
>> an anonymous object - this is set in SimpleLazyObject.__init__).
>>
>
> The Python compiler can do strange things with assignment to __class__ in
> the presence of super. This issue has now been fixed, but it may be what is
> biting you:
>
>     http://bugs.python.org/issue12370
>
> If this *is* the problem, then see the workaround suggested in the issue.
> (alias super to _super in the module scope and use the old style super
> calling convention.)
>
> Michael
>
>
>>
>> Puzzling!
>>
>> Regards,
>>
>> Vinay Sajip
>>
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> http://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
>> http://mail.python.org/mailman/options/python-dev/fuzzyman%40voidspace.org.uk
>>
>
>
>
> --
>
> http://www.voidspace.org.uk/
>
> May you do good and not evil
> May you find forgiveness for yourself and forgive others
>
> May you share freely, never taking more than you give.
> -- the sqlite blessing http://www.sqlite.org/different.html
>
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> http://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> http://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>



-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-Dev mailing list