We know that with notation:
class Foo(object):
a = 1
def __init__(self):
self.b = 2
def c(self):
print('c')
we can create static variable Foo.a, 'normal' variable b, which will be available after creating and instance of Foo, and method c
Today I was really surprised, that I can use conditional statements in a class, but outside of scope of the function
class C():
if True:
a = 1
b = 2
Languages like C++/Java, taught me that legal notation is similar to:
class Name():
variable = <expression>
Could you describe other rules, which refer to this specific scope? How I should name this scope?
The class body is just Python code. It has specific scope rules, but anything goes otherwise. This means you can create functions conditionally:
class C:
if some_condition:
def optional_method(self):
pass
or pull methods from elsewhere:
import some_module
class D:
method_name = some_module.function_that_accepts_self
etc.
The Python documentation for class definitions states:
A class definition is an executable statement.
and
The class’s suite is then executed in a new execution frame (see section Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains only function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary.
Note the usually in that text. Essentially, the class body is executed as a function would, and anything you put in the body namespace becomes an attribute on the class.
The Naming and binding section then tells you:
The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods
so names you define in this block cannot be directly accessed in methods; you'd use class.name or self.name instead.
In java everything is classes and object, classes are container but in python everything is object.
Classes are also objects. like functions(also objects) so when you use conditional statement in function then python allows you to do same in Classes.
like:-
def A():
if condition:
do something
elif condition:
do somethig
else:
do something
is same
Class A()
if condition:
do something
elif condition:
do somethig
else:
do something
you can assign functions even to store in a variable like you do for classes
def A():
pass
a = A # is valid
while in java you can't define function outside the classes.
Related
class ExampleClass():
def Example(self):
self.nestedinstance = self.NestedClass()
self.nestedinstance.makenew()
class NestedClass():
def makenew(self):
newclass = NestedClass()
ExampleClass().Example()
When I run the above code I get the exception: name 'NestedClass' is not defined
Is there a different way to do this with a nested class or have I done something wrong?
You ideally want to be using classmethods if creating a new instance, this is an example of how you'd do it:
class NestedClass():
#classmethod
def makenew(cls):
newclass = cls()
Alternatively if you wanted to create an instance using the current instance (for example if you needed to pass in some arguments), then you can get the class by using type(self) or self.__class__.
class NestedClass():
def makenew(self):
newclass = type(self)()
Without knowing your use case though, this may not be what you're after.
Your error comes from how python handles classes.
When it encounters a class statement, the body of the class is run, and the names it defines are placed in a separate namespace, which will eventually become the class __dict__. The class object is not created and bound to its name until (well) after the body has run. That means that when you put class NestedClass: inside the body of class ExampleClass:, ExampleClass does not exist yet, and neither does NestedClass. Indirectly because of this, all the new class namespaces live in the top level available namespace (e.g. global or function), and are not actually nested within one another.
As a consequence of this order of operations, class bodies are not aware of the namespaces of surrounding classes at all. So the namespace of NestedClass looks out to the global namespace, not to the __dict__ of ExampleClass, as you might expect coming from say Java. A class defined in a function would be able to see the functions local namespace before globals, but still not that of an enclosing class.
And so, the line newclass = NestedClass() raises an error. The name NestedClass does not exist in the function's namespace, or in the global namespace. There are three simple workarounds available:
Use the staticly scoped __class__:
newclass = __class__()
Refer to the class by its global name:
newclass = ExampleClass.NestedClass()
Don't use nested classes in Python. This is generally the preferred approach. Just move NestedClass to the top level. Then your makenew method will work without modification, and ExampleClass.Example can refer to NestedClass directly instead of as self.NestedClass.
In contrast to functions, a class' body is executed at definition time:
class A(object):
print 'hello'
Out:
hello
Why is it the case? Is it related to #classmethod / #staticmethod methods and class attributes?
Everything is executed at the module level when Python first imports a module. Function bodies (and generator expression bodies) are the exception here, not the rule. Python executes everything to create the objects contained in a module; like everything in Python, classes are objects, and so are functions.
The only reason a class body uses a separate code object is because a class body is executed in a separate namespace, with that namespace then forming the class attributes. Class bodies are not the only such namespaces; set and dict comprehensions, and in Python 3, list comprehensions are also executed with a separate namespace, scoping their locals.
So functions and generator expressions are the exception, expressly because their whole purpose is to be executed at a later time. Note that the function definition is executed:
>>> import dis
>>> dis.dis(compile('def foo(): pass', '<stdin>', 'exec'))
1 0 LOAD_CONST 0 (<code object foo at 0x106aef2b0, file "<stdin>", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
9 LOAD_CONST 1 (None)
12 RETURN_VALUE
The MAKE_FUNCTION bytecode there creates the function object, together with the stored bytecode for that function, and the result is bound to the global name foo.
Class objects are no different here; the class statement produces a class object, and as part of that object, we need to know the attributes from the class body.
If Python did not execute the class body, other code could not make any use of those class members. You couldn't access class attributes (including class methods and static methods), you couldn't set class attributes, etc.
Any functions that are part of the class body are of course not executed at that time. Just like top-level functions, only a MAKE_FUNCTION bytecode is executed and the resulting local name (set with STORE_FAST) is then turned into a class attribute, analogous to a global function object being bound to a global with STORE_NAME.
According to Class definitions - Python documentation:
A class definition is an executable statement. It first evaluates the
inheritance list, if present. Each item in the inheritance list should
evaluate to a class object or class type which allows subclassing. The
class’s suite is then executed in a new execution frame (see section
Naming and binding), using a newly created local namespace and the
original global namespace. (Usually, the suite contains only function
definitions.) When the class’s suite finishes execution, its execution
frame is discarded but its local namespace is saved. A class
object is then created using the inheritance list for the base classes
and the saved local namespace for the attribute dictionary. The class
name is bound to this class object in the original local namespace.
Consider these two classes A and B:
class A:
p=4
def add(i, j):
return i + j
class B:
p = add(2, 2)
a = A()
b = B()
print("a.p:",a.p)
print("b.p:",b.p)
Both have similar function and in both p is equal to 4. This occurs in definition and not instantiation.
In definition of class B the value of p is calculated and is used later during instantiation. This means everything about these properties is created beforehand.
I am currently reviewing the python tutorials of python.org. I come from C++ and in the Classes tutorial (https://docs.python.org/3/tutorial/classes.html) I see that the scoping is similar to that in C++. It says the following about scoping and nesting:
"At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
- the innermost scope, which is searched first, contains the local names
- the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
- the next-to-last scope contains the current module’s global names
- the outermost scope (searched last) is the namespace containing built-in names "
However I tried with following code from the same page:
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick) #this is the troublesome self
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.add_trick('roll over') #without the self this complains
>>> e.add_trick('play dead')
>>> d.tricks
['roll over', 'play dead']
If I remove the self in self.tricks.append(trick) the code will not compile and throw an NameError: name 'tricks' is not defined when calling the function d.add_trick('roll over').
Why does it happen? As I understand from the paragraph above, the function add_trick should look for a variable called tricks first within its own local scope, then if doesn't find any, in the nearest enclosing scope, which is the scope of the Class Dog, and there it should find it, without the need of using self. What am I missing?
As the tutorial said, scopes are searched in the order local, nonlocal, global, builtin.
The nonlocal scope is for enclosing functions. A class declaration is not a function. Its namespace gets thrown away after it is used to create the class object's __dict__, so variables at the class level cannot produce nonlocals in enclosed functions. Think of class-level assignments and variable reads like implicit assignments to and reads from a hidden dict, rather than as function locals. (Metaclasses can even replace this hidden dict with some other mapping.)
But the class scope does add one nonlocal, __class__. This is rarely used directly, but it's important for the zero-argument form of super().
This is the class object itself, so it's uninitialized until the class declaration finishes executing. So __class__.tricks would work inside a method if it's called after the class body executes (the usual case), but not if it's called during the execution of the class body.
There are other scopes to be aware of in Python. Comprehensions create a local scope like functions do. (They're basically compiled like generator functions--the kind with yield inside.) Also, caught exceptions are automatically deleted at the end of their handling clause to prevent a reference cycle.
You can see locals namespace using the locals() builtin and globals using globals(). The builtin scope is just the builtins module. The nonlocals are tricky. They'll actually show up in locals() if the compiler sees them being used. Function objects keep a reference to the nonlocals they use in their __closure__ attribute, which is a tuple of cells.
Your mistake is in thinking that the class is a scope. It isn't. As the doc you quoted explains, scopes are functions or modules.
Does this example help:
In [27]: foobar = 'pre'
In [28]: class AClass():
...: print('class def:', foobar)
...: foobar = 'class'
...: def __init__(self):
...: print('init:', foobar)
...: print(self.foobar)
...: self.foobar='instance'
...: print(self.foobar)
...:
class def: pre
In [29]: AClass.foobar
Out[29]: 'class'
Class definition is like running a function. foobar is initially the global value, but then gets reassigned, and is now available as part of the class namespace.
In [30]: x = AClass()
init: pre
class
instance
In [31]: x.foobar
Out[31]: 'instance'
In [32]: x.__class__.foobar
Out[32]: 'class'
When we define an instance, foobar comes from the outer, global namespace. self.foobar initially accesses the class namespace, but then gets redefined to be an instance variable.
Changing the global foobar is reflected in the next instance creation:
In [33]: foobar = 'post'
In [34]: y = AClass()
init: post
class
instance
In [35]: y.__class__.foobar
Out[35]: 'class'
Your tutorial page, in section 9.3.1. Class Definition Syntax says that while in the class definition, there's a new local namespace. That's where foobar='class' is defined. But once out of the class definition, that namespace is renamed as AClass.
The instance creation runs outside of the class definition. So it 'sees' the global foobar, not the class local one. It has to specify the namespace.
The distinction between scope when a class (or function) is defined, and when it is 'run' can be confusing.
A class definition in particular creates a class scope, which is a special kind of scope. While the class scope is indeed enclosed by the global scope (class variables can access global variables), the class scopes DO NOT ENCLOSE the local scopes within it! So, the local method scopes within the class body cannot access the class scope during name lookup. (At least without qualifying it). In other words, a class's scope is only accessible from within the top level codebody of its own class definition. it is inaccessible from anywhere else, be it inside or outside, without using dot notation directly
I have a question about inner classes usage in python. I know that this is a bad practice but anyway. I am wondering about scope where inner class is defined. I got an error 'global name 'ClassName' is not defined'. My code snippet looks like this:
I discovered that to avoid getting this error I can use:
ClassWithEnum.EnumClass
instead of:
EnumClass
inside of doSomethingWithEnum() function. So I am wondering if there is any other way to make EnumClass defined inside of doSomethingWithEnum() function? And why there is no such error when I declare EnumClass as a default parameter in doSomethingWithEnum() function?
class ClassWithEnum(object):
class EnumClass(object):
...
def doSomethingWithEnum(self, m = EnumClass....):
...
Python class construction executes as code. The def statement is really a line of code being executed that creates a function. The class keyword introduces a namespace. Putting these two mechanisms together, it means that class EnumClass really creates an object by that name in the current namespace, not much different from what foo = 'bar' does, so within the same namespace you can refer to it by that name, which is what happens in the def statement.
Also compare:
class Foo:
bar = 'baz'
print bar
baz = bar
Every line of code inside a class block is a regular executable line of code.
Once your class definition is done, you're out of the ClassWithEnum namespace and cannot access EnumClass anymore simply by that name; it's now only available as ClassWithEnum.EnumClass; whether from "outside" the class or from within a function (any function, including class methods).
To get access to the class without typing its name from within the method you could do:
type(self).EnumClass
Or simply self.EnumClass, since properties are looked up up the chain.
When you are inside doSomethingWithEnum function, you are in the different namespace. To access anything that is defined in your class, like EnumClass, you should call self.EnumClass. If it were a class method, it would be cls.EnumClass.
I am trying to understand the nesting of namespaces in python 2.7.
Consider the following not-working code:
class c(object):
def debug(self):
print globals(),locals()
print x,y
class a(object):
x=7
def __init__(self):
self.y=9
class b(object):
def debug(self):
print globals(),locals()
print x,y
class d(c):
pass
How do I access to the variables x and y, from the calls
a().b().debug()
a.b().debug()
a().d().debug()
a.d().debug()
None of them seems able to see either x nor y.
EDIT after discussion, it seems that what I want (avoid reference to globals) can be reached only by explicitly extending the information on the nested classes. For instance
class a(object):
#
#classmethod
def _initClass(cls):
for v in dir(cls):
if type(cls.__dict__[v])==type:
setattr(cls.__dict__[v],'vader',cls)
#
x=7
class b(object):
def debug(self):
print b.vader.x
class d(c):
pass
a._initClass()
And even this technique does not seem useful to access an instance variable, as intended in the a().d().debug sequence.
class objects do not create a scope; class bodies are executed just once and discarded, the local namespace producing the class attributes. Class bodies never participate in nested scopes; they are ignored entirely when resolving non-local names.
As such, your x = 7 is not a name that the nested b class (or its methods) could ever access. Instead, it is a class attribute on a. Accessing a.x will work. y is an instance attribute, and you'll have to have a reference to the instance for it to be accessible anywhere else.
Note that this applies to class b as well; it is a class attribute on a now, just like x is a class attribute.
There is nothing special about your class b other than how you reference the class object. Just because you created an instance of a does not mean that b has any privileged access to it; a().b() does not create a relationship between the instances. You could do:
b = a.b
b_instance = b()
and there would be no difference. You could even do:
a.b.a = a
a.b.a()
and the world will not implode! (fancy that).
Martijn already gave a good answer, but I'll take a stab at my own.
As Martijn said, class declarations are executed rather like one-off functions, with their own local scope, when their module is first imported. Whatever's left over in this local scope, after everything in the class declaration has been executed, is used as the class's dictionary. So x, __init__, b, and d all end up being attributes on the a class object. The same is true of your classes b and d; their bodies are executed when the module is imported and the local scopes left over are used as their dictionaries as well.
The reason your code isn't working is that, by the time the debug method executes, the only scopes it's aware of are the global scope and its own local scope. In python, methods do not implicitly include a class instance's dictionary as part of their scope as they do in languages like C++. The class instance is available explicitly as the self argument which appears in the argument list (hence, Python's zen "explicit is better than implicit" -- try import this in the python console).
Also, it doesn't matter whether or not you instantiate a before accessing and instantiating the other classes b and d on a since b and d are both class attributes on a. Therefore, python can successfully retrieve b and d from either an instance of a or a direct reference to the a class object.