0

I do have a class with multiple methods in which I'd like to add constant values of instances of this class, to keep common used combinations handy.

class Text:
    GREETING = Text('Hello')
    LOREM = Text('Lorem ipsum dolor sit amen')

    def __init__(self, text):
        self.text = text

    def double(self):
        return f'{self.text}, {self.text}'

This doesn't work in that way (Undefined name 'Text'). I could declare the constants later on:

Text.GREETING = Text('Hello')
Text.LOREM = Text('Lorem ipsum dolor sit amen')

But that doesn't seem quite nice to me. I'd like to have it all inside of the class definition to be able to document everything nicely. Is there any other way possible?

9
  • 3
    Why not use enum ? Commented Jul 22, 2020 at 9:40
  • 1
    The problem is that inside the class definition the class is still not defined (you are defining it now) so you can't use it to create instances. What would you think about a class method that registers these common globals? Commented Jul 22, 2020 at 9:49
  • "But that doesn't seem quite nice to me" well, that's your only option, really. You could create some @classmethod that adds those constants to the class, but you still have to call it manually after Commented Jul 22, 2020 at 9:50
  • @bigbounty: The real objects are quite more complex. Using enums doesn't make any sense in this case to me. Say the class would be car and I would like to add some commonly used cars. VW Golf, Skoda Octavia, … I could use a enum if I only have one parameter (e.g. size). But not if I have multiple independent attributes. Commented Jul 22, 2020 at 11:15
  • @juanpa.arrivillaga That would be possible indeed, but I'd have to call it anyway. At least I would capsulate the actual creation. Commented Jul 22, 2020 at 11:16

2 Answers 2

2

You might make use of class- or static methods, if you don't mind the extra paranthesis and construction at call site:

class Text:
    @staticmethod
    def lorem():
        return Text("Lorem ipsum")
    # or
    @classmethod
    def greeting(cls):
        return cls("Hello")
Sign up to request clarification or add additional context in comments.

1 Comment

That would be great, especially if I'd use the 'constants' as bases that could be modified afterwards – if I recall the Method, the Text would be regenerated.
1

Does this look better to you?

class Text:
    def __init__(self, text):
        self.text = text

    @classmethod
    def register(cls, name, text):
        setattr(cls, name, text)

Text.register('GREETING', 'hello')
Text.register('LOREM', 'Lorem ipsum dolor sit amen')

EDIT: In case you need this pattern for multiple classes, it can be easily extracted to a separate class and use it as a Mixin:

class Registry:
    @classmethod
    def register(cls, name, text):
        setattr(cls, name, text)

class Text(Registry):
    def __init__(self, text):
        self.text = text

Text.register('GREETING', 'hello')
Text.register('LOREM', 'Lorem ipsum dolor sit amen')

2 Comments

Indeed it does. It doesn't solve the problem directly but 'streamlines' the generation of those base classes.
If you want to have multiple classes with this pattern you can always move the classmethod to a parent class from where the other classes inherit. I will edit my answer to add this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.