msg80161 - (view) |
Author: (Somelauw) |
Date: 2009-01-19 12:41 |
>>> f = Fraction() >>> f.a = 5 >>> f.__slots__ ('_numerator', '_denominator') >>> f.a 5 >>> f.__dict__ {} When I create my own object, this doesn't happen. >>> class Slots: __slots__ = ("slot1", "slot2") >>> a = Slots() >>> a.slot3 = 6 Traceback (most recent call last): File "<pyshell#4>", line 1, in a.slot3 = 6 AttributeError: 'Slots' object has no attribute 'slot3' >>> In python2 this only happens when __slots__ is a tuple. (When __slots__ is a list, it works correctly) >>> class Slots: __slots__ = ("slot1", "slot2") >>> a = Slots() >>> a.slot3 = 8 >>> Here is a copy-paste from the python3 documentation: Without a __dict__ variable, instances cannot be assigned new variables not listed in the __slots__ definition. Attempts to assign to an unlisted variable name raises AttributeError. If dynamic assignment of new variables is desired, then add '__dict__' to the sequence of strings in the __slots__ declaration. Any non-string iterable may be assigned to __slots__. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key. |
|
|
msg80183 - (view) |
Author: Benjamin Peterson (benjamin.peterson) *  |
Date: 2009-01-19 15:33 |
The problem is that Fraction inherits from a class without __slots__ (Rationale), so it's useless. I suggest that the __slots__ be removed or Rationale.register() is used instead of inheritance. |
|
|
msg80212 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-19 21:35 |
I believe that __slots__ was used for performance (memory, speed) reasons here rather than for preventing random attribute assignments. But maybe inheriting from Rational invalidates those reasons as well... |
|
|
msg80213 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-19 21:37 |
The Decimal class has the same issue in py3k (but not in the trunk). |
|
|
msg80225 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-19 23:46 |
Arghh! Decimal is NOT supposed to inherit or register with numbers. Guido has pronounced on this and we've discussed it multiple times. See the comments in numbers.py which were supposed to serve as a reminder. Decimals are not interoperable with floats. All instances of Real are supposed to interoperate but Decimal('1.1') does not add to float(1.1). Please rip this out of Py3.0's Decimal module. |
|
|
msg80226 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-20 00:03 |
For the Fractions issue, consider adding an empty __slots__ declaration to every level in numbers.py. That will preclude unintended dictionary creation for anything inheriting from the numbers abcs. We should also be an issue for the other abcs. The collections ABCs are less affected because they are not as granular as number objects. So their overall memory footprint only grows by a small percentage from the inclusion of an instance dictionary. |
|
|
msg80227 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-20 00:03 |
Py3.0.1 should not go out without this being fixed. |
|
|
msg80235 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-20 07:29 |
Fixed the decimal issue in r68800 and r68799 . Still needs a fix to Fractions, preferably adding an empty __slots__ to all levels of numbers.py. |
|
|
msg80261 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-20 17:52 |
A random data point: just for fun, I just tried assessing the impact of __slots__ on Decimal instances, by the crude method of putting all of the Decimal instances that are created during a complete run of the Decimal test suite (over 100000 of them) into a list and watching memory usage. This was on a non-debug 32-bit build of py3k, with 16-bit Py_UNICODE (which is relevant because the coefficients of Decimal instances are strings). Results: (*) ~44 bytes per Decimal on average with __slots__ ~183 bytes per Decimal on average without __slots__ The effect on speed wasn't really significant: removing __slots__ gives at worst a 1-2% slowdown on a complete run of the test-suite. So please let's not remove __slots__ from Fraction! (*) raw numbers: 120343 total number of Decimals. The following are memory readings from the RSIZE column of top. with __slots__: putting 8 copies of each Decimal into list -> 33M total usage putting 4 copies of each Decimal into list -> 55M total usage without __slots__: putting 8 copies of each Decimal into list -> 182M total usage putting 4 copies of each Decimal into list -> 96M total usage. I took the liberty of subtracting 4 bytes per list entry, to compensate for the memory taken by the list itself. |
|
|
msg80262 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-20 17:57 |
> ~44 bytes per Decimal on average with __slots__ > ~183 bytes per Decimal on average without __slots__ ...and of course a difference of 140 bytes shouldn't really be much of a surprise: Python 3.1a0 (py3k:68809M, Jan 20 2009, 16:55:13) [GCC 4.0.1 (Apple Inc. build 5490)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.getsizeof(dict()) 140 |
|
|
msg80265 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-20 19:43 |
Thanks for the patch, Raymond. I'm don't really have any experience with ABCs. I've read the PEP (a few times), but am not convinced that I fully understand all the ideas involved. What are the practical differences between having Fraction inherit from Rational directly, and registering Fraction as a subclass of Rational? |
|
|
msg80267 - (view) |
Author: Jeffrey Yasskin (jyasskin) *  |
Date: 2009-01-20 19:55 |
Rational has default definitions for some of its methods and properties. If Fraction inherits from Rational, it gets those definitions implicitly. If it's registered with Rational, it has to define them itself. I don't know that much about __slots__ (or I'd have known that just defining it on Fraction wouldn't work :-/) but if it doesn't prevent subclasses from having dicts, it seems like a good idea to add an empty __slots__ to most classes in the ABC hierarchy, and definitely the numeric ones. |
|
|
msg80269 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-20 20:19 |
Got it. Thanks, Jeffrey. The patch looks good to me---please go ahead and apply. |
|
|
msg80272 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-20 20:35 |
Fixed in the trunk: r68813. Benjamin, can you please apply to 2.6, 3.0 and 3.1. |
|
|
msg80276 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-01-20 20:49 |
BTW, Raymond, it looks as though your earlier commit, r68799, changed distutils/command/wininst-8.0.exe. Was that deliberate? |
|
|
msg80282 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-01-20 21:27 |
Thanks Mark. Fixed in r68819 . |
|
|
msg81762 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-02-12 13:23 |
This needs to be merged before 3.0.1 goes out. I can't do it right now since I don't have ssh access; will do it when I get home if no-one beats me to it. |
|
|
msg81790 - (view) |
Author: Mark Dickinson (mark.dickinson) *  |
Date: 2009-02-12 18:07 |
Merged (manually) to py3k in r69547; svnmerged to 3.0 and 2.6 in r69548, r69549. |
|
|