I came across "unqualified on right hand side" phrase while reading oops concept in python for usage like self._customer = customer. What that phrase trying to explain?
Complete statement is
For example, the command, self._customer = customer, assigns the instance variable self._customer to the parameter customer; note that because customer is unqualified on the right-hand side, it refers to the parameter in the local namespace. --Data Structures and Algorithms in Python p. 72
According to the Python docs
qualified name
A dotted name showing the “path” from a module’s global scope to a class, function or method defined in that module, as defined in PEP 3155. For top-level functions and classes, the qualified name is the same as the object’s name:
...
When used to refer to modules, the fully qualified name means the entire dotted path to the module, including any parent packages, e.g. email.mime.text:
Put more simply, qualifying a name in Python means that you explicitly define its scope. Thus self._customer is a qualified name (it identifies the instance variable customer for the enclosing class) whereas the bare customerreference does not specify any scope qualifications.
When a name is unqualified, Python applies Lexical Scoping rules to try and find the variable, searching (in order)
Local variables (including function parameters)
Variables local to any outer functions, if we're dealing with a nested function definition
Global variables
Built-in variables
Related
Suppose I have the following code:
def outer(information):
print(locals())
def inner():
print("The information given to me is: ", information)
return inner
func1 = outer("info1")
print(func1)
It returns:
{'information': 'info1'}
<function outer.<locals>.inner at 0x1004d9d30>
Of course, if I call func1, it will print with info1 in the statement. So, from printing the locals() in the outer function, I can see that there is some relationship between the local scope and the storage of the argument.
I was expecting func1 to simply be outer.inner, why does the syntax instead say outer.<locals>.inner? Is this a syntactical way of clarifying that there are different local scopes associated to each of these functions - imagine I made another one func2 = outer("info2") - I return using the outer function?
Also, is there something special about the enclosing <> syntax when used around a name? I see it around both the object and locals.
See PEP 3155 -- Qualified name for classes and functions and the example with nested functions.
For nested classes, methods, and nested functions, the __qualname__ attribute contains a dotted path leading to the object from the module top-level. A function's local namespace is represented in that dotted path by a component named <locals>.
Since the __repr__ of a function uses the __qualname__ attribute, you see this extra component in the output when printing a nested function.
I was expecting func1 to simply be outer.inner
That's not a fully qualified name. With this repr you might mistakenly assume you could import the name outer and dynamically access the attribute inner. Remember the qualname is a "dotted path leading to the object", but in this case attribute access is not possible because inner is a local variable.
Also, is there something special about the enclosing <> syntax when used around a name?
There is nothing special about it, but it gives a pretty strong hint to the programmer that you can't access this namespace directly, because the name is not a valid identifier.
You can think of outer.<locals>.inner as saying that inner is a local variable created by the function. inner is what is referred to a closure in computer science. Roughly speaking a closure is like a lambda in that it acts as a function, but it requires non-global data be bundled with it to operate. In memory it acts as a tuple between information and a reference to the function being called.
foo = outer("foo")
bar = outer("bar")
# In memory these more or less looks like the following:
("foo", outer.inner)
("bar", outer.inner)
# And since it was created from a local namespace and can not be accessed
# from a static context local variables bundled with the function, it
# represents that by adding <local> when printed.
# While something like this looks a whole lot more convenient, it gets way
# more annoying to work with when the local variables used are the length of
# your entire terminal screen.
<function outer."foo".inner at 0x1004d9d30>
There is nothing inherently special about the <> other than informing you that <local> has some special meaning.
Edit:
I was not completely sure when writing my answer, but after seeing #wim's answer <local> not only applies to closures created consuming variables within a local context. It can be applied more broadly to all functions (or anything else) created within a local namespace. So in summary foo.<local>.bar just means that "bar was created within the local namespace of foo".
As you may know, the scope of a variable is statically determined in python (What are the rules for local and global variables in Python?).
For instance :
a = "global"
def function():
print(a)
a = "local"
function()
# UnboundLocalError: local variable 'a' referenced before assignment
The same rule applies to classes, but it seems to default to the global scope instead of raising an AttributeError:
a = "global"
class C():
print(a)
a = "local"
# 'global'
Moreover, in the case of a nested function, the behavior is the same (without using nonlocal or global) :
a = "global"
def outer_func():
a = "outer"
def inner_func():
print(a)
a = "local"
inner_func()
outer_func()
# UnboundLocalError: local variable 'a' referenced before assignment
But in the case of nested classes, it still defaults to the global scope, and not the outer scope (again without using global or nonlocal) :
a = "global"
def outer_func():
a = "outer"
class InnerClass:
print(a)
a = "local"
outer_func()
# 'global'
The weirdest part is that the nested class default to the outer scope when there is no declaration of a :
a = "global"
def outer_func():
a = "outer"
class InnerClass:
print(a)
outer_func()
# 'outer'
So my questions are :
Why the discrepancy between functions and classes (one raising an exception, the other defaulting to the global scope.
In nested classes, why the default scope has to become global instead of keeping using the outer one when using a variable defined afterward?
The answer is given in great detail in Section 9.2 of the official docs. The crux of the matter is
... On the other hand, the actual search for names is done dynamically, at run time — however, the language definition is evolving towards static name resolution, at “compile” time, so don’t rely on dynamic name resolution! (In fact, local variables are already determined statically.)
When you are in the class definition, which at the moment of its execution is the innermost scope, dynamic name resolution applies. You therefore see printouts of the global value of a.
If the name resolution were static, as in function definitions, the name a would be recognized as a local name even in the print statement. That is why you can't print a in a function before assigning to it.
The rules for class body scoping are alluded to in Section 4.2.2:
Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace.
Let's parse that last sentence carefully, because it fully covers your last two examples. First off, what is an unbound local variable in this context? A class body creates a new namespace, just like entering a function. If a name is bound somewhere in a class body, it is a local variable. This is determined statically, as mentioned above. If you attempt to reference the name before it is first bound, you have an unbound local variable. Instead of raising an error, as a function call would do, python jumps straight to the global namespace to perform the lookup (and ignores builtins as well). In all other cases (not local variables), normal LEGB lookup order applies.
This is indeed a bit counter-intuitive, and I would argue that it pushes if not outright breaks the rule of least surprise.
From the docs:
A scope is a textual region of a Python program where a namespace is directly accessible. “Directly accessible” here means that an unqualified reference to a name attempts to find the name in the namespace.
Why does the documentation use the word "directly" while defining "scope"? Has it got some significance? Will it make a difference if "scope" is defined as a textual region of a Python program where a namespace is accessible?
A name space is always accessible by qualifying a reference. It is directly accessible if the reference does not need to be qualified.
How to explicitly declare a list as a local variable that cannot be touched from anywhere except the function its declared in?
tried
LOCAL variable = []
doesnt work
Python is the interpreted language and it hasn't such statements.
Here is from the documentation:
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice
You can notice such _pseudo_private_var(one underscore) naming.It is just a convention, it just tells you SHOUDN'T touch this variable but you CAN change value of this one at the same time. It is a python). There is __dynamic_obj_relative_naming as well(two underscores).
More about scopes and namespaces rules you could find here Classes, namespace and scope rules. There are few interesting statements you are interested in probably global and nonlocal. They are like opposites of yours.
Almost same as question Where are the local, global, static, auto, register, extern, const, volatile variables are stored?, the difference is this thread is asking how Python language implement this.
Of all those, Python only has "local", "global" and "nonlocal" variables.
Some of those are stored in a Dictionary or dictionary like object, which usually can be explicitly addressed.
"global": Actually "global" variables are global relatively to the module where they are defined - sometimes they are referred to as "module level" variables instead of globals, since most of evils of using global variables in C do not apply - since one won't have neither naming conflicts neither won't know wether a certain name came from when using a module-level global variable.
Their value is stored in the dictionary available as the "__dict__" attribute of a module object. It is important to note that all names in a module are stored in this way - since names in Python point to any akind of object: that is, there is no distinction at the language level, of "variables", functions or classes in a module: the names for all these objects will be keys in the "__dict__" special attribute, which is accessed directly by the Language. Yes, one can insert or change the objects pointed by variables in a module at run time with the usual "setattr", or even changing the module's __dict__ directly.
"local": Local variables are available fr "user code" in a dictionary returned by the "locals()" buil-in function call. This dictionary is referenced by the "f_locals" attribute of the current code frame being run. Since there are ways of retrieving the code frame of functions that called the current running code, one can retrieve values of the variables available in those functions using the f_locals attribute, although in the CPython implementation, changing a value in the f_locals dictionary won't reflect on the actuall variable values of the running code - those values are cached by the bytecode machinery.
"nonlocal" Variables are special references, inside a function to variables defined in an outter scope, in the case of functions (or other code, like a class body) defined inside a function. They can be retrieved in running code, by getting the func_closure attribute - which is a tuple of "cell" objects. For example, to retrieve the value of the first nonlocal variable inside a function object, one does:_
function.func_closure[0].cell_contents - the values are kept separate from the variable names, which can be retrieved as function.func_code.co_varnames. (this naming scheme is valid for Python 2.x)
The bottom-line: Variable "values" are always kept inside objects that are compatible with Python objects and managed by the virtual machine. Some of these data can be made programmatically accessible through introspection - some of it is opaque. (For example, retrieving, through introspection, nonlocal variables from inside the function that owns them itself is a bit tricky)