Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #24804 > unrolled thread

Dictless classes

Started bySteven D'Aprano <steve+comp.lang.python@pearwood.info>
First post2012-07-03 05:03 +0000
Last post2012-07-03 19:25 -0400
Articles 5 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  Dictless classes Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-07-03 05:03 +0000
    Re: Dictless classes alex23 <wuwei23@gmail.com> - 2012-07-02 22:50 -0700
    Re: Dictless classes Duncan Booth <duncan.booth@invalid.invalid> - 2012-07-03 09:38 +0000
      Re: Dictless classes Roy Smith <roy@panix.com> - 2012-07-03 08:28 -0400
    Re: Dictless classes Terry Reedy <tjreedy@udel.edu> - 2012-07-03 19:25 -0400

#24804 — Dictless classes

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-07-03 05:03 +0000
SubjectDictless classes
Message-ID<4ff27d28$0$11103$c3e8da3@news.astraweb.com>
You can create instances without a __dict__ by setting __slots__:

py> class Dictless:
...     __slots__ = ['a', 'b', 'c']
... 
py> Dictless().__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Dictless' object has no attribute '__dict__'


But the class itself still has a __dict__:

py> Dictless.__dict__
dict_proxy({'a': <member 'a' of 'Dictless' objects>, 'c': <member 'c' of 
'Dictless' objects>, 'b': <member 'b' of 'Dictless' objects>, 
'__module__': '__main__', '__slots__': ['a', 'b', 'c'], '__doc__': None})


I wonder whether there is some metaclass magic one can do to create a 
class without a __dict__?


I don't have a use-case for this. But I have some code which assumes that 
every class will have a __dict__, and I wonder whether that is a safe 
assumption.



-- 
Steven

[toc] | [next] | [standalone]


#24807

Fromalex23 <wuwei23@gmail.com>
Date2012-07-02 22:50 -0700
Message-ID<6a9a2166-db2f-4af1-a4be-d2f1e327fa4a@d6g2000pbt.googlegroups.com>
In reply to#24804
On Jul 3, 3:03 pm, Steven D'Aprano <steve
+comp.lang.pyt...@pearwood.info> wrote:
> I don't have a use-case for this. But I have some code which assumes that
> every class will have a __dict__, and I wonder whether that is a safe
> assumption.

Remember the recent thread on using a different implementation for
<object>.__dict__?
https://groups.google.com/group/python-ideas/browse_frm/thread/f15ef3c7b702a1fa

Given it was impossible to have it *not* create a conventional dict
via metaclasses, I would assume that there will always be a .__dict__.

[toc] | [prev] | [next] | [standalone]


#24811

FromDuncan Booth <duncan.booth@invalid.invalid>
Date2012-07-03 09:38 +0000
Message-ID<XnsA0856B054AB3Fduncanbooth@127.0.0.1>
In reply to#24804
Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:

> You can create instances without a __dict__ by setting __slots__:

That is a necessary but not a sufficient condition. An instance of a class 
can be created without a dict only if (either you set __slots__ or you 
implement it in C without a __dict__ attribute) AND none of its base 
classes require a dict.

Setting __slots__ when a base class requires that its instances have a 
__dict__ doesn't prevent creation of the __dict__.

> 
> But the class itself still has a __dict__:

The class is an instance of 'type'. Instances of 'type' require a dict 
therefore every class requires a dict. Except of course for old style 
classes in Python 2.x but they have a __dict__ too.

Also you cannot create a subclass of 'type' with non-empty slots (it throws 
a type error "nonempty __slots__ not supported for subtype of 'type'"). 
However I don't think that's really relevant as even if they did allow you 
to use __slots__ it wouldn't prevent the creation of a __dict__ for the 
'type' base class.

> I don't have a use-case for this. But I have some code which assumes
> that every class will have a __dict__, and I wonder whether that is a
> safe assumption.

I believe so.

-- 
Duncan Booth http://kupuguy.blogspot.com

[toc] | [prev] | [next] | [standalone]


#24814

FromRoy Smith <roy@panix.com>
Date2012-07-03 08:28 -0400
Message-ID<roy-3F5730.08280003072012@news.panix.com>
In reply to#24811
In article <XnsA0856B054AB3Fduncanbooth@127.0.0.1>,
 Duncan Booth <duncan.booth@invalid.invalid> wrote:

> Also you cannot create a subclass of 'type' with non-empty slots (it throws 
> a type error "nonempty __slots__ not supported for subtype of 'type'"). 
> However I don't think that's really relevant as even if they did allow you 
> to use __slots__ it wouldn't prevent the creation of a __dict__ for the 
> 'type' base class.

I played around a bit trying to write a metaclass which implemented:

def __getattribute__(self, name):
   if name == "__dict__":
      raise AttributeError

but didn't get very far.  Maybe somebody with stronger metaclass-fu than 
I have could run with this idea?

[toc] | [prev] | [next] | [standalone]


#24840

FromTerry Reedy <tjreedy@udel.edu>
Date2012-07-03 19:25 -0400
Message-ID<mailman.1767.1341357962.4697.python-list@python.org>
In reply to#24804
On 7/3/2012 1:03 AM, Steven D'Aprano wrote:
> You can create instances without a __dict__ by setting __slots__:

Each *instance* does not have its own dict because each would be equal, 
therefore only one hidden mapping is needed, somewhere. But attribute 
names must be mapped to objects somehow.

> I wonder whether there is some metaclass magic one can do to create a
> class without a __dict__?

If every 'class' instance of the metaclass has the same attributes, then 
it would not be necessary for each 'class' to have its individual dict. 
But would you call such things 'classes'?

 > I don't have a use-case for this. But I have some code which assumes
 > that every class will have a __dict__, and I wonder whether that is a
 > safe assumption.

It depends what you mean by a class. A 'metaclass' is just a callable 
that accepts 3 args. The only constraint appears that its return must be 
callable (and accept at least one arg).

class M():
     __slots__ = ()
     def __init__(*args): pass
     def __call__(*args): pass

class C(metaclass = M): pass

c=C()
print(type(C), C, c, hasattr(C, '__dict__'))

#
<class '__main__.M'> <__main__.M object at 0x000000000220A1C0> None False

Is C a dictless class? Your choice ;-).

Actually, Python thinks not. If we add
     class Mclassob(object): pass
and have __call__ return an instance thereof and try
     c.__class__ = C
we get
     TypeError: __class__ must be set to a class, not 'M' object

-- 
Terry Jan Reedy


[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web