0
class ILinkedListElem:
    @property
    def value(self):
        raise NotImplementedError

    @property
    def next(self):
        raise NotImplementedError


class ListElem(ILinkedListElem):
    def __init__(self, value, next_node=None):
        self.value = value
        self.next = next_node

I wanna something like this. This abstract variables definition works for class vars, but not for instance

I want to all instances of ILinkedListElem subclass must has "value" and "next" attributes

KrySeyt
  • 31
  • 2
  • This has nothing to do with abstract classes. You didn't define a setter for either property. Neither `value` nor `next` is an instance attribute. – chepner Nov 19 '22 at 22:34
  • Does this have what you're looking for? https://stackoverflow.com/questions/5960337/how-to-create-abstract-properties-in-python-abstract-classes – Vin Nov 19 '22 at 22:38
  • @Vin, No, this question about class variables, but I need to instances variables – KrySeyt Nov 19 '22 at 22:41
  • @chepner Yes, I didnt. This example of class var declaration. I wanna something like this, but for class instance vars – KrySeyt Nov 19 '22 at 22:43
  • So all you want to do is ensure that a subclass of `ILinkedListElem` defines `value` and `next` attributes? Just set them in an inherited `__init__` method. – chepner Nov 19 '22 at 23:09
  • @chepner yes, but ```__init__``` may be overriden in subclass without calling ```super().__init__()```. I was want to require all of this vars in instances. My problem already solved. Thanks – KrySeyt Nov 19 '22 at 23:39
  • A subclass can override anything it wants in any way. You're leaving it to the user to define `__init__` in the first place, and the user can also override the two properties. At some point, you just have to trust that the user isn't going to obviously shoot themselves in the foot, because there's nothing you can do to stop it. – chepner Nov 19 '22 at 23:42
  • @chepner Thanks, I'll take that into consideration. With properties, this atleast requires two properties with same names inside subclass, but ```__init__``` will not requires anything, I think – KrySeyt Nov 19 '22 at 23:46
  • Nothing requires a subclass to define *anything*. You can use the inherited ones (you'll get a `NotImplemented` error if you try to use them, sure, but subclassing will still work). Even if the subclass does override them, nothing says they have to assign properties (even if you use the `abc` module; it doesn't enforce overriding an abstract property with another property, only with *something*) to those names. – chepner Nov 19 '22 at 23:52
  • Maybe you are using a type checker of some kind that won't allow the type of the inherited names to be changed, but that's not indicated in the question. (Honestly, it looks more like you are writing Java with a Pythonic accent than actual Python.) – chepner Nov 19 '22 at 23:53
  • @chepner Oh, I hadn't thought of that. Thanks for help, I will try to make my python code more pythonic – KrySeyt Nov 20 '22 at 00:02

1 Answers1

0

If you want to force/require all instances of any subclass of ILinkedListElem to have the attributes "value" and "nxt", the following standard implementation with abstractmethod seems to do what you're after:

from abc import ABC, abstractmethod

class ILinkedListElem (ABC):
    @property
    @abstractmethod
    def value(self):
        raise NotImplementedError

    @property
    @abstractmethod
    def nxt(self):
        raise NotImplementedError

This is the abstract class, from which we create a compliant subclass:

class ListElem_good (ILinkedListElem):
    
    def __init__(self, value, next_node=None):
        self._value = value
        self._nxt = next_node
        
    @property
    def value(self):
        return self._value
    
    @property
    def nxt(self):
        return self._nxt

We create an instance of this compliant subclass and test it:

x = ListElem_good('foo', 'bar')
print (x.value)
print (x.nxt)

#result:
    # foo
    # bar

If we create a non-compliant subclass that omits an implementation of nxt, like so:

class ListElem_bad (ILinkedListElem):
    
    def __init__(self, value):
        self._value = value
        
        
    @property
    def value(self):
        return self._value

when we try to create an instance of this non-compliant subclass:

y = ListElem_bad('foo')
print (y.value)

it fails:

    y = ListElem_bad('foo')

TypeError: Can't instantiate abstract class ListElem_bad with abstract methods nxt

This relies on essentially the same solution offered here, which you suggested in a comment-exchange does not meet your requirements. But when applied to your specific use-case above, it appears to precisely address the issue you've raised - or have I misunderstood?

Vin
  • 929
  • 1
  • 7
  • 14
  • Thank you, this is actually what I need, I couldn't think of _value in __init__ and value property instead of just value in __init__ – KrySeyt Nov 19 '22 at 23:32