Descriptor to restrict input
Your solution just doesn't work


Your validation check always fails. Yes int(value) != int is always true. I don't think an instance of a class will ever be the class that it's an instance of.
Your mutating a class variable. The tool you're utilizing forces you to take instances, normally there's a pretty good reason.

If we remove the previous error and run your code we can easily see, there's no point in having more than one instance of a Player.

&gt;&gt;&gt; a = Person()
&gt;&gt;&gt; b = Person()
&gt;&gt;&gt; a.moods['happy'].__set__(a, 8)
&gt;&gt;&gt; b.moods['happy'].__get__(b, None)
8  # Ok, that's not right...



I don't believe you've actually tried to code you've provided. And honestly what's the point in a single-data non-singleton class? The provided code is just untested garbage.

You're using it wrong

If it's not evident enough that you're fighting a tool that is pure sugar. Then you're not doing it right. The instance has to keep the state of the instance, and the descriptor has to interact with a varying amount of instances to interact with their state correctly.

If anything of the instance's leaks out into the descriptor, or vice versa. Then you're going to have a bad, bad time.

Since descriptors are to be tied onto classes I'm making a Mood class. Since the descriptor needs to have a place to store data. We can define that in the __init__ of Mood. To note, because you may not notice this by yourself. self._values can be mutated to bypass the validator. Using self._values[mood] = value is not how you update values, use setattr(self, mood, value).

In addition to fixing OneDigitNumericValue, you should make it take an argument that is the validator for the function. If you need another validator it'd be better and simpler to make a simple hard to mess-up function. Rather than making lots of potentially broken descriptors.

def single_digit(value):
    if 0 &lt;= value &lt;= 9:
        return
    raise ValueError("The value is invalid")


class Validator:
    def __init__(self, validator):
        self.validator = validator
        self.name = None

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

    def __get__(self, instance, owner) -&gt; object:
        return instance._values[self.name]

    def __set__(self, instance, value) -&gt; None:
        self.validator(value)
        instance._values[self.name] = value


class Mood:
    happy = Validator(single_digit)
    angry = Validator(single_digit)
    sad = Validator(single_digit)

    def __init__(self):
        self._values = {}
        self.happy = 5
        self.angry = 5
        self.sad = 5

    def update_states(self, states):
        for mood, value in states.items():
            setattr(self, mood, value + getattr(self, mood))


And it actually works:

&gt;&gt;&gt; a = Mood()
&gt;&gt;&gt; b = Mood()
&gt;&gt;&gt; a.happy = 3
&gt;&gt;&gt; a.happy
3
&gt;&gt;&gt; b.happy
5
&gt;&gt;&gt; a.update_states({'happy': 3})
&gt;&gt;&gt; a.happy
6