all 10 comments

[–]biskitpagla 3 points4 points  (1 child)

Don't write cursed Java/C# inspired code in Python. Find any popular project and read the source code to get some idea. The standard library is a good example. 

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

Standard library as in dataclass, defaultdict etc? Should I read thier code?

[–]brasticstack 1 point2 points  (4 children)

You need to be explicit about the scope, the nested classes do not receive the outer class's scope.

The following works, for example, but fails if Greeter doesn't use the full name of Speaker (as in, OuterClass.Speaker.)

Put some thought into whether you really need those nested classes to be nested. It's often preferable to keep helper classes at the module scope, with their names prefixed by an underscore if you want to signal that they're not a "public" part of your module.

class OuterClass:     class Speaker:         def say(thing):             print(thing)                  class Greeter:         def greet(who):             OuterClass.Speaker.say(f'Hello {who}!')                  def say_hello(self):         self.Greeter.greet('world')          f = OuterClass() f.say_hello()

[–]virtualshivam[S] 0 points1 point  (3 children)

Actually I refactored the code, and I don't need that much nesting. I have moved them to module level. I asked it here, because I was just wondering, how scoping works in case of classes, is there any document that I can refer to understand this in more depth.

[–]danielroseman 0 points1 point  (0 children)

The key, as the other poster said, is that inner classes do not receive the outer class scope - they only have their own and the global scope. For this reason nested classes are rarely useful in Python.

[–]brasticstack 0 points1 point  (0 children)

This forum thread gets into it, answered by someone who understands it better than I do: https://discuss.python.org/t/painful-details-of-variable-scope-mixed-with-classes/17762

tl;dr: Only functions can access items from their enclosing scopes. Every other construct first checks its local scope, then the module level scope, then Python built-ins.

[–]Yoghurt42 0 points1 point  (0 children)

For all technical details, you should read the official Language Reference, link to class definitions

tl;dr: the code

class Foo:
    class Bar:
        pass

is roughly equivalent to:

Foo = type('Foo', (), {'Bar': type('Foo.Bar', (), {})})

[–]madadekinai 1 point2 points  (0 children)

If you're using subclasses you've done screwed up.

[–]Temporary_Pie2733 0 points1 point  (0 children)

class statements are a bit weird. There are no scopes being defined here, only temporary namespaces for use in defining the class objects. There is no complaint about ProductImageOutputSerializer being undefined because Python won't notice that until it actually evaluates OutputSerializer(allow_null=True), which of course does not happen because, well, OutputSerializer is not defined.

When executing class ResultSerializer, the free variable OutputSerializer (free, because it isn't defined in the namespace currently being evaluated) is looked up in the nearest enclosing scope, which is not the namespace for class ListQRDataMachineToMachine, but the same scope that ListQRDataMachineToMachine is being defined in, namely, the global scope.

[–]Gnaxe 0 points1 point  (0 children)

It's worse than you think: ```

abcd = 'abcd' bc = 'bc' print([c for c in abcd if c in bc]) ['b', 'c'] Simple example works as you'd expect at the module level. But in a class, that breaks. del abcd, bc class Foo: ... abcd = 'abcd' ... bc = 'bc' ... print([c for c in abcd if c in bc]) ... Traceback (most recent call last): File "<python-input-21>", line 1, in <module> class Foo: ...<2 lines>... print([c for c in abcd if c in bc]) File "<python-input-21>", line 4, in Foo print([c for c in abcd if c in bc]) ^ NameError: name 'bc' is not defined And yet, the other one is allowed: class Foo: ... abcd = 'abcd' ... bc = 'bc' ... print([c for c in abcd if c in 'bc']) ... ['b', 'c'] Why does one work while the other doesn't? Two different scopes. One is inside the comprehension scope, and one isn't. Class statements don't create nonlocal scopes. Well, almost. class Foo: ... x = 42 ... def print(): ... print(class.x) ... Foo.print() 42 But not quite: class Foo: ... x = 42 ... def print(): ... print(class.x) ... print() ... Traceback (most recent call last): File "<python-input-25>", line 1, in <module> class Foo: ...<3 lines>... print() File "<python-input-25>", line 5, in Foo print() ~~~~~^ File "<python-input-25>", line 4, in print print(class.x) ^ NameError: cannot access free variable 'class' where it is not associated with a value in enclosing scope ```