0

I am new to your community. Sorry for my English. I am interested in Python languages. Please help me understand descriptors. I don't know how to use descriptors and _slots_ in class Calendar at the same time. Here is an example of my code:

    class dateValue:
    def __checkValue(value):
        if isinstance(value, int) or isinstance(value, float):
            return True
        return False

    def __set_name__(self, owner, name):
        self.__name = name

    def __get__(self, instance, owner):
        return instance.__dict__[self.__name]

    def __set__(self, instance, value):
        if dateValue.__checkValue(value):
            instance.__dict__[self.__name] = value
        else:
            raise ValueError("Неверный формат данных")

    def __delete__(self, instance):
        del instance.__dict__[self.__name]

    class Calendar:
    
        #__slots__ = ["day", "month", "year"]
    
        day = dateValue()
        month = dateValue()
        year = dateValue()
    
        def __init__(self, day=0, month=0, year=0):
            self.day = day
            self.month = month
            self.year = year

cal4 = Calendar()
cal4.day = 3
cal4.month = 3
cal4.year = 2023

day4 = cal4.day
month4 = cal4.month
year4 = cal4.year

print(day4, month4, year4, sep=".")
Ahmad
  • 274
  • 2
  • 15
  • *stop using double-underscore name mangling*. Why are you doing that? – juanpa.arrivillaga Jan 02 '21 at 08:24
  • Anyway, the whole point of `__slots__` is that instances don't have a `__dict__`. Addtionally, `__slots__` *work through* descriptors, so you can't use class variables with the same name. If you just create an empty class but with those slots, and look at `vars(MyClass)` you'll see that they are there – juanpa.arrivillaga Jan 02 '21 at 08:39
  • using @property would be a better and easier solution. – Alex Dec 02 '22 at 11:43

1 Answers1

1

BLUF: if Calendar uses __slots__, it won't have a __dict__ attribute (that's the whole point of slots).

Per the python language reference (Notes on using __slots__):

__slots__ are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by __slots__; otherwise, the class attribute would overwrite the descriptor assignment.

There are two things you can do to fix the error and keep your code working (mainly) the same way.

  1. Don't use __slots__. They deny the creation of a __dict__, and you want the __dict__.
  2. (What I prefer), your class dateValue can own the underlying value and return it on __get__, instead of replacing the accessor with the value. your Calendar can keep its __slots__ and offload the additional values out of sight.
Dharman
  • 30,962
  • 25
  • 85
  • 135