What/Why does this print? [duplicate] - python

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.

Related

Confusion about scoping in python classes

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

Private Variables and Class-local References

I am learning Python from here.
In Section 9.6 (Private Variables and Class-local References), the last paragraph states that:
Notice that code passed to exec, eval() or execfile() does not
consider the classname of the invoking class to be the current class;
this is similar to the effect of the global statement, the effect of
which is likewise restricted to code that is byte-compiled together.
The same restriction applies to getattr(), setattr() and delattr(), as
well as when referencing dict directly.
I do not understand what they mean. Please provide an explanation or give me some examples to demonstrate this concept.
Imagine you have a class with a local reference:
class Foo:
__attr= 5
Inside the class, this attribute can be referenced as __attr:
class Foo:
__attr= 5
print(__attr) # prints 5
But not outside of the class:
print(Foo.__attr) # raises AttributeError
But it's different if you use eval, exec, or execfile inside the class:
class Foo:
__attr= 5
print(__attr) # prints 5
exec 'print(__attr)' # raises NameError
This is explained by the paragraph you quoted. exec does not consider Foo to be the "current class", so the attribute cannot be referenced (unless you reference it as Foo._Foo__attr).
class Foo:
Foo._Foo__attr= 5
print(Foo._Foo__attr) # prints 5
exec 'print(Foo._Foo__attr)' # CORRECTED REFERENCE, PRINTS OUTPUT 5
# exec does not consider Foo to be
#the "current class",
# so the private attribute cannot be referenced
#(unless you reference it as Foo._Foo__attr).

Python memory allocation, when using bound, static or class functions?

I am curious about this: what actually happens to the python objects once that you create a class that contains each one of these functions?
Looking at some example, I see that either the bound, static or class function is in fact creating a class object, which is the one that contains all 3 function.
Is this always true, no matter which function I call? and the parent object class (object in this case, but can be anything I think) is always called, since the constructor in my class is invoking it implicitly?
class myclass(object):
a=1
b=True
def myfunct(self, b)
return (self.a + b)
#staticmethod
def staticfunct(b):
print b
#classmethod
classfunct(cls, b):
cls.a=b
Since it was not clear: what is the lifecycle for this object class, when I use it as following?
from mymodule import myclass
class1 = myclass()
class1.staticfunct(4)
class1.classfunct(3)
class1.myfunct
In the case of static, myclass object get allocated, and then the function is run, but class and bound method are not generated?
In the case of class funciton, it is the same as above?
in the case of the bound function, everything in the class is allocated?
The class statement creates the class. That is an object which has all three functions, but the first (myfunct) is unbound and cannot be called without an instance object of this class.
The instances of this class (in case you create them) will have bound versions of this function and references to the static and the class functions.
So, both the class and the instances have all three functions.
None of these functions create a class object, though. That is done by the class statement. (To be precise: When the interpreter completes the class creation, i. e. the class does not yet exist when the functions inside it are created; mind boggling, but seldom necessary to know.)
If you do not override the __init__() function, it will be inherited and called for each created instance, yes.
Since it was not clear: what is the lifecycle for this object class,
when I use it as following?
from mymodule import myclass
This will create the class, and code for all functions. They will be classmethod, staticmethod, and method (which you can see by using type() on them)
class1 = myclass()
This will create an instance of the class, which has a dictionary and a lot of other stuff. It doesn't do anything to your methods though.
class1.staticfunct(4)
This calls your staticfunct.
class1.classfunct(3)
This calls you classfunct
class1.myfunct
This will create a new object that is a bound myfunct method of class1. It is often useful to bind this to a variable if you are going to be calling it over and over. But this bound method has normal lifetime.
Here is an example you might find illustrative:
>>> class foo(object):
... def bar(self):
... pass
...
>>> x = foo()
>>> x.bar is x.bar
False
Every time you access x.bar, it creates a new bound method object.
And another example showing class methods:
>>> class foo(object):
... #classmethod
... def bar():
... pass
...
>>> foo.bar
<bound method type.bar of <class '__main__.foo'>>
Your class myclass actually has four methods that are important: the three you explicitly coded and the constructor, __init__ which is inherited from object. Only the constructor creates a new instance. So in your code one instance is created, which you have named class1 (a poor choice of name).
myfunctcreates a new integer by adding class1.a to 4. The lifecycle of class1 is not affected, nor are variables class1.a, class1.b, myclass.a or myclass.b.
staticfunct just prints something, and the attributes of myclass and class1 are irrelevant.
classfunct modifies the variable myclass.a. It has no effect on the lifecycle or state of class1.
The variable myclass.b is never used or accessed at all; the variables named b in the individual functions refer to the values passed in the function's arguments.
Additional info added based on the OP's comments:
Except for the basic data types (int, chars, floats, etc) everything in Python is an object. That includes the class itself (a class object), every method (a method object) and every instance you create. Once created each object remains alive until every reference to it disappears; then it is garbage-collected.
So in your example, when the interpreter reaches the end of the class statement body an object named "myclass" exists, and additional objects exist for each of its members (myclass.a, myclass.b, myclass.myfunct, myclass.staticfunct etc.) There is also some overhead for each object; most objects have a member named __dict__ and a few others. When you instantiate an instance of myclass, named "class1", another new object is created. But there are no new method objects created, and no instance variables since you don't have any of those. class1.a is a pseudonym for myclass.a and similarly for the methods.
If you want to get rid of an object, i.e., have it garbage-collected, you need to eliminate all references to it. In the case of global variables you can use the "del" statement for this purpose:
A = myclass()
del A
Will create a new instance and immediately delete it, releasing its resources for garbage collection. Of course you then cannot subsequently use the object, for example print(A) will now give you an exception.

Conditional statements in a class, but outside of scope of the function

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.

namespace for class inside of class in python

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.

Categories

Resources