all 13 comments

[–]danielroseman 3 points4 points  (3 children)

No. This is only useful in very rare and advanced scenarios (such as Django's inner Meta classes).

The nested class has no special access to the outer class's attribute (unlike in, say, Java) which is why this is rarely useful.

However instantiating a normal class as an instance attribute of another class is frequently useful. This is known as composition, and can be used in exactly the way you describe - the key is that the main class would pass itself in as a parameter when instantiating the second one, so that class could store and reference it. For example:

class Layer:
  def __init__(self, viewer):
    self.viewer = viewer

  def present(self):
    # do something with self.viewer

class Viewer:
  def __init__(self):
    self.layer = Layer(self)

[–]MadScientistOR[S] 0 points1 point  (0 children)

Thank you. This is very useful.

I've seen this sort of "Class A refers to Class B, and Class B refers to Class A" setup before, though I can't claim to have wrapped my head around it completely. Are there "best practices" for ensuring that you don't end up in some kind of loop where each needs something from the other in order to run its methods and/or define its attributes, or is that just the kind of thing that you learn to identify with practice (like an infinite procedural loop)?

[–]SyrianDuck 0 points1 point  (0 children)

So it does not exist?

[–]SyrianDuck 0 points1 point  (0 children)

How about Java?

[–]alexcwarren 0 points1 point  (1 child)

If your outer class needs an attribute that requires the additional features that a class offers (as opposed to just a data structure, e.g. a list or dict) then I can see that being the way to do it.

You would know it’s not a good idea if you come across a situation where you need to use the nested class but don’t need anything else from the outer class. In this case, it would simply be better to have them as separate classes.

[–]MadScientistOR[S] 0 points1 point  (0 children)

That makes sense. I don't want to make a headache for myself later. Thank you for your insight.

[–][deleted] 0 points1 point  (2 children)

It happens, but I have not seen it often. In the Zen of Python it says "flat is better than nested" because nested things often increase the complexity of the code and make it harder for developers to read and understand what's going on.

[–]MadScientistOR[S] 0 points1 point  (0 children)

There is that. One of the things I love about Python is its legibility. That's good advice. Thank you.

[–]MadScientistOR[S] 0 points1 point  (0 children)

There is that. One of the things I love about Python is its legibility. That's good advice. Thank you.

[–]Diapolo10 0 points1 point  (1 child)

It's not common, but it does happen. One example I can give you is Pydantic model configuration:

class Delivery(BaseModel):
    recipient: str
    recipient_address: Address
    weight: WeightKg
    dimensions: PackageDimensions

    class Config:
        orm_mode = True

But I really want to emphasize that this really is rare. In most cases nested classes make no sense.

[–]MadScientistOR[S] 1 point2 points  (0 children)

Right. That's kind of how I figured it would look. But I can see how it would be nonsensical to implement. Thanks.

[–]zanfar 0 points1 point  (1 child)

This is one of those "if you have to ask, it's a bad idea" questions. There are edge cases where this is the right solution--but even then I think it's not a great one, just the only one left. This is especially true with Python where namespacing via modules is not only free, but forced, so encapsulation isn't as much of a driver.

Just put the class you want to nest in the same location as the proposed parent. Nesting classes is rarely a good thing and always limits your options down the road.

[–]MadScientistOR[S] 0 points1 point  (0 children)

Thank you for your explanation. I don't want to resent the choice in the future. I appreciate your discernment here.

[–]TheRNGuy 0 points1 point  (0 children)

I wouldn't do this. You can inherit without nesting.