1

I have googled around for some time, but what I got is all about instance property rather than class property. For example, this is the most-voted answer for question from stackoverflow

class C(ABC):
    @property
    @abstractmethod
    def my_abstract_property(self):
        return 'someValue'

class D(C)
    def my_abstract_property(self):
        return 'aValue'

class E(c)
   # I expect the subclass should have this assignment,
   # but how to enforce this?
   my_abstract_property = 'aValue'  

However, that is the instance property case, not my class property case. In other words, calling
D.my_abstract_property will return something like <unbound method D.my_abstract_property>. Returning 'aValue' is what I expected, like class E.

Niko Föhr
  • 28,336
  • 10
  • 93
  • 96
Gogle
  • 158
  • 1
  • 9
  • 1
    So you want a class variable that is constant for all subclass instances? – Frank C. Mar 06 '20 at 10:27
  • Yes. That's indeed what I want. – Gogle Mar 06 '20 at 10:29
  • Not exactly. I do want a class variable, but I want it to be constant for all its "instances", not "subclass". I expect all subclass of "C" to have a class property with the same name, but value can vary. – Gogle Mar 06 '20 at 10:45

3 Answers3

1

Based on your example and comment to my previous reply, I've structured the following which works with ABC. :

from abc import ABC

class C(ABC):
    _myprop = None

    def __init__(self):
        assert self._myprop, "class._myprop should be set"

    @property
    def myprop(self):
        return self._myprop


class D(C):
    _myprop = None

    def __init__(self):
        super().__init__()


class E(C):
    _myprop = 'e'

    def __init__(self):
        super().__init__()


e = E()
print(e.myprop)

d = D()
print(d.myprop)

You are correct that there is no Python pre-scan that will detect another developer has not assigned a value to a class variable before initializing. The initializer will take care of notifying pretty quickly in usage.

Frank C.
  • 7,758
  • 4
  • 35
  • 45
  • Almost there. I expect "C.myprop" to be "None", and each of C's subclass has its own value of "myprop". In your code, D still needs to do one more function call to set its own value. Can the developer of subclass assign "myprop" in the implementation of his subclass without a external function call? – Gogle Mar 06 '20 at 11:34
0

You can use @classmethod decorator.

j suman
  • 127
  • 4
  • I tried, it seems not working. If c is declared with abc.ABCMeta, and have a method called "my_abstract_property" decorated by @classmethod, and D inherets C, calling 'D.my_abstract_property` returns '>'. Can you share some code that can work correctly? – Gogle Mar 06 '20 at 10:58
0

I come up with a tricky workaround.

class C(object):
    myProp = None
    def __init__(self):
        assert self.myProp, 'you should set class property "name"'

class D(C):

    def __init__(self):
        C.__init__(self)

class E(C):
    myProp = 'e'
    def __init__(self):
        C.__init__(self)

print(D.myProp)
print(E.myProp)

But it still has some problems:

  1. D.myProp will not raise any exception to warn the developer about the constraint (assigning myProp as its class property), until the developer initialize an instance of his class.
  2. abc module cannot work with this solution, which means loss of lots of useful features of that module
Gogle
  • 158
  • 1
  • 9