0

I am working with Python's decimal module, but when I do:

>>>from decimal import Decimal
>>>d = Decimal('3.14')
>>>d.__slots__
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'decimal.Decimal' object has no attribute '__slots__'
>>>Decimal.__slots__
raceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: type object 'decimal.Decimal' has no attribute '__slots__'

But when I inspect Decimal class in PyCharm (_pydecimal.py), I see:

class Decimal(object):
    """Floating point class for decimal arithmetic."""

    __slots__ = ('_exp','_int','_sign', '_is_special')
...

Supposedly, I should be able to get __slots__ from class/instance, but I didn't. What am I missing here? (This kinda behaves like Python's built-in int class.)

vanbastelaer
  • 368
  • 2
  • 15
  • Possible duplicate of https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-single-and-double-underscore-before-an-object-name. – Shane Bishop Jan 20 '21 at 17:24
  • 1
    @ShaneBishop Can you elaborate why this question is a possible duplicate of naming conventions? – vanbastelaer Jan 20 '21 at 17:28
  • The answers in that question say that names with a leading double underscore are subjected to python naming mangling, which might explain what was going on. But I'm no python expert, so I could be wrong. – Shane Bishop Jan 20 '21 at 17:33
  • Are you trying to solve a particular problem here, or just understanding the implementation? – Karl Knechtel Jan 20 '21 at 17:33
  • @KarlKnechtel I am just trying to verify that my understanding of `__slots__` and `__dict__` usage in Python is correct, because I was surprised that I was able to use `__dict__` (instead of `__slots__`) to get all attributes of Decimal class for my own class that inherits Decimal. – vanbastelaer Jan 20 '21 at 17:37
  • @ShaneBishop no, that isn't it – juanpa.arrivillaga Jan 20 '21 at 17:44
  • 1
    @vanbastelaer PyCharm is lying to you. `Decimal` is implemented in C. They basically write stubs – juanpa.arrivillaga Jan 20 '21 at 17:45

1 Answers1

2

If you look at decimal.py, you'll see this:

try:
    from _decimal import *
    from _decimal import __doc__
    from _decimal import __version__
    from _decimal import __libmpdec_version__
except ImportError:
    from _pydecimal import *
    from _pydecimal import __doc__
    from _pydecimal import __version__
    from _pydecimal import __libmpdec_version__

It first tries to import from _decimal, which is a precompiled shared library on my system. The code you found via PyCharm is instead in the fallback _pydecimal implementation. I suspect your code is in fact loading the _decimal version of Decimal, which simply doesn't use __slots__.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • Thanks @Mark. You are probably right. Is there a programmatically way to find out which version (without modifying `decimal.py` to e.g. print something out)? I tried `inspect.getmodule()` but it just gives me `decimal.py`. – vanbastelaer Jan 20 '21 at 17:32
  • @vanbastelaer. You may be able to do something like inspect the `__name__` or `__module__` attributes of some of the imported classes and functions, not that I expect it will do much good. – Mad Physicist Jan 20 '21 at 17:43
  • 1
    @vanbastelaer if you are using a standard CPython distribution (e.g. from the official installer, from `conda` etc) then you are definitely using the C implemenation – juanpa.arrivillaga Jan 20 '21 at 17:46