3

Working on a class that has sub properties. Is the below code a good practice / Pythonic? If not, have any suggestion?

GOAL

exp = ExCls()
prop1 = exp.subprop.prop1
exp.print_prop2()
## prop1 = 1
## prints 2

EXAMPLE CODE

class ExCls():
   class subprop:
      prop1 = 1
      prop2 = 2
   def print_prop2(self):
      print self.subprop.prop2
4
  • 1
    Note that subprop is shared between all instances of ExCls, is this intentional? Commented Oct 9, 2015 at 18:00
  • You should read through the Tutorial a couple of times then have a look at the property built-in function and maybe look through the Descriptor How To Guide. Commented Oct 9, 2015 at 18:12
  • @GingerPlusPlus, I had overlooked that fact when building. Thank you. Commented Oct 9, 2015 at 22:41
  • @wwii, thanks for the property reference. This will be helpful : ) Commented Oct 9, 2015 at 22:42

2 Answers 2

4

In most of the common higher level languages, dot notation is used to indicate namespace. The same is true for Python. Take the following useless class for example:

>>> class UselessClass(object):
...     @property
...     def and_on(self):
...         return self
...     def forever(self):
...         return "I can see into forever"
>>> this_goes_on = UselessClass()
>>> this_goes_on.and_on.and_on.and_on.and_on.and_on.forever()
'I can see into forever'

All it's doing is returning itself (an instantiated object of type UselessClass), which has access to all of it's own properties.

The only issue with your code is, as GingerPlusPlus pointed out, you're making subprop shared between all instances of ExCls. This may be desired, but (based on the question), also may not be. Here's an instance of why this is bad:

>>> test1 = ExCls()
>>> test2 = ExCls()
>>> test1.subprop.prop1
1
>>> test2.subprop.prop1 = 2
>>> test1.subprop.prop1
2

As you can see, this isn't generally the behaviour you'd expect. Instead, what you may be looking to do is:

class ExCls(object):
    def __init__(self):
        class subprop:
            prop1 = 1
            prop2 = 2
        self.subprop = subprop()

    def print_prop2(self):
        print(self.subprop.prop2)

Overall, I'd highly recommend going back and reading up on Python's Classes, and how they work.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @Rejected I have been enlighten.
3

I would advice using the right tool for the job – if I'd want my subprop to only contain some data, I'd use types.SimpleNamespace:

from types import SimpleNamespace

class Useless:
    def __init__(self):
        self.subprop = SimpleNamespace(prop1=1, prop2=2)

or, it's close-enough immutable sibling, collections.namedtuple:

from collections import namedtuple

class Useless:
    Subprop = namedtuple('Subprop', 'prop1, prop2')
    def __init__(self):
        # two lines below does the same, choose more readable one
        self.subprop = Subprop(1, 2)
        self.subprop = Subprop(prop1=1, prop=2)

If I'd want it to also contain some methods, I'd use simple, custom object:

class Useless:
    class Subprop:
        def __init__(self, prop1, prop2):
            self.prop1 = prop1
            self.prop2 = prop2
        def sum(self):
            return self.prop1 + self.prop2
    def __init__(self):
        # two lines below does the same, choose more readable one
        self.subprop = Subprop(1, 2)
        self.subprop = Subprop(prop1=1, prop2=2)

1 Comment

Very interesting @GingerPlusPlus... Thank you for this input as well! : )

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.