Overriding Methods in Python Subclasses

From PEP 435 , subclass enumerations allow:

>>> class Foo(Enum):
...   def some_behavior(self):
...     pass
...
>>> class Bar(Foo):
...   happy = 1
...   sad = 2
...

Let's say I want to define in a some_behaviordifferent way for enumerations happyand sad.

Is there a better way to do this than something like:

>>> class Bar(Foo):
...   happy = 1
...   sad = 2
...   def some_behavior(self):
...       if self is Bar.happy:
...           # happy behavior
...       elif self is Bar.sad:
...           # sad behavior

It looks awkward for me.

+4
source share
2 answers

No no.

I mean, you could do something like this:

def some_behavior(self):
    return {Bar.happy: some_function
            Bar.sad: some_other_function}[self](arguments?)

Or like this:

def some_behavior(self):
    custom_thing = {Bar.happy: some_function
                    Bar.sad: some_other_function}[self]
    # do something which is the same for both
    custom_thing()
    # do something else the same for both

some_function .. , , ( , ). , , , ( functools.partial ).

, - :

class Foo(Enum):
    happy = 1
    sad = 2

def happy_behavior():  # No self argument!
    self = Foo.happy  # only if you need self
    ...

def sad_behavior():
    self = Foo.sad
    ...

Foo.happy.some_behavior = happy_behavior
Foo.sad.some_behavior = sad_behavior

, , , Foo(1).some_behavior() Foo['sad'].some_behavior(). , / .

+3

, 1.

__getattribute__, 2:

class Foo(Enum):

    def __getattribute__(self, name):
        # overriding this method is dangerous!
        #
        # enum member value must be an instance of a class
        value_dict = super().__getattribute__('_value_').__class__.__dict__
        if name in value_dict:
            # bind the enum member instance to the method and return it
            return partial(value_dict[name], self)
        else:
            # otherwise return the found object unchanged
            return super().__getattribute__(name)

    def __repr__(self):
        # clean up the repr()
        return '<%s.%s>' % (self.__class__.__name__, self.name)

:

def member(cls):
    # convert the class into an instance of itself
    return cls()

Enum:

class Bar(Foo):

    #
    # default methods
    #
    def some_behavior(self):
        return self.name + ' is neutral'

    def likes_to(self):
        return 'likes to sit'

    #
    # members
    #
    @member
    class happy:
        # overridden methods
        def some_behavior(self):
            return self.name + ' is happy'
        def likes_to(self):
            return 'likes to dance'

    @member
    class sad:
        # overridden method
        def some_behavior(self):
            return self.name + ' is sad'

    @member
    class okay:
        # uses default methods
        pass

:

>>> list(Bar)
[<Bar.happy>, <Bar.sad>, <Bar.okay>]

>>> Bar.happy.some_behavior()
'happy is happy'

>>> Bar.happy.likes_to()
'likes to dance'

>>> Bar.sad.some_behavior()
'sad is sad'

>>> Bar.sad.likes_to()
'likes to sit'

>>> Bar.okay.some_behavior()
'okay is neutral'

>>> Bar.okay.likes_to()
'likes to sit'

+1 .

2 __getattribute__ , - , object.__getattribute__. .


: Python stdlib Enum, enum34 Advanced Enumeration (aenum).

0

Source: https://habr.com/ru/post/1609151/


All Articles