2

I'm trying to validate and format a class variable. The class extends a class with ABCMeta as its __metaclass__ and I can't yet instantiate my child class. So when I run this below code it prints property object and not the output I want, which I understand why. But then how do I do it?

from abc import ABCMeta, abstractproperty

class RuleBase(object):
    __metaclass__ = ABCMeta

    id = None
    id = abstractproperty(id)

    @property
    def format_id(self):
        try:
            _id = 'R%02d' % self.id
        except TypeError:
            raise TypeError("ID must be an integer")
        return _id

    @classmethod
    def verbose(cls):
        print cls.format_id

class Rule(RuleBase):
    id = 1

Rule.verbose()  # prints property object and not R01

In my theory, I think this would work.

class FormattingABCMeta(ABCMeta):
    def __new__(mcl, classname, bases, dictionary):
        # Format here, remove format_id property from RuleBase, 
        # and use FormattingABCMeta as metaclass for RuleBase.
        return super(C, mcl).__new__(mcl, classname, bases, dictionary)

But then I feel I'm twisting it too much. So, how to do this? And is my understanding correct? Any help is appreciated.

Anshu Kumar
  • 606
  • 6
  • 18
  • 1
    Properties only work on **instances**, not on classes. They are simply not bound to a class. Since `verbose` is a class method, you can't use `cls.format_id`. You'd have to make `format_id` a classmethod too and call it. – Martijn Pieters May 08 '16 at 21:58
  • 1
    The alternative is to create a [class property descriptor](http://stackoverflow.com/questions/5189699/how-can-i-make-a-class-property-in-python). – Martijn Pieters May 08 '16 at 22:00

1 Answers1

2

Not entirely sure what your goal is but you would need to use fget on the property object passing cls to get the _id:

 print cls.format_id.fget(cls)
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Yes that would work. Thank you. However, is this the most pythonic way to do this? Also, does my goal look too skewed? I mean I have certain Rules extending RuleBase and I want their verbosity to be printed. Does doing it without creating their instances sound weird? – Anshu Kumar May 08 '16 at 21:59
  • This'd work provided the `id` attribute is always a class attribute. – Martijn Pieters May 08 '16 at 22:01
  • @AnshuKumar, as Martijn commented below your question, the other option is to make it a classmethod and print cls.format_id() but this will work fine presuming you are dealing with class attributes which from your question I presumed you were. – Padraic Cunningham May 08 '16 at 22:03