Gangmax Blog

Python notes 1: scope, built-in functions and statements

Scope

From here.

“LEGB” order rule
  1. L, Local — Names assigned in any way within a function (def or lambda)), and not declared global in that function.

  2. E, Enclosing function locals — Name in the local scope of any and all enclosing functions (def or lambda), from inner to outer.

  3. G, Global (module) — Names assigned at the top-level of a module file, or declared global in a def within the file.

  4. B, Built-in (Python) — Names preassigned in the built-in names module : open,range,SyntaxError,…

New scope

Essentially, the only thing in Python that introduces a new scope is a function definition. Classes are a bit of a special case in that anything defined directly in the body is placed in the class’s namespace, but they are not directly accessible from within the methods (or nested classes) they contain.

Restrictions: Variables in scopes other than the local function’s variables can be accessed, but can’t be rebound to new parameters without further syntax. Instead, assignment will create a new local variable instead of affecting the variable in the parent scope.

In order to actually modify the bindings of global variables from within a function scope, you need to specify that the variable is global with the global keyword.

In Python 2 the list comprehension does not create a variable scope, however in Python 3 the loop variable is created in a new scope.

Built-in Functions

A full list of the built-in functions(76 totally) of Python(2) can be found here.

dir()

Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> import struct
>>> dir() # show the names in the module namespace
['__builtins__', '__doc__', '__name__', 'struct']
>>> dir(struct) # show the names in the struct module
['Struct', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into',
'unpack', 'unpack_from']
>>> del struct
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> class Shape(object):
def __dir__(self):
return ['area', 'perimeter', 'location']
>>> s = Shape()
>>> dir(s)
['area', 'perimeter', 'location']
>>> del __builtins__
>>> dir()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'dir' is not defined

Note the code above:

  1. The “import” statement adds a module into the current globel scope;

  2. This “del” statement can remove name from the current scope, including the default ones like “__builtins__“;

  3. After you remove the default “__builtins__“, the built-in fuctions are unavailable.

And you can monkey patch the built-in functions as well.

1
2
3
4
5
>>> abs(-10)
10
>>> setattr(__builtins__, 'abs', lambda x: x + 10)
>>> abs(-10)
0

Statements

print

In Python2, “print” is a statement. While in Python3 the “print” statement is replaced by the “print()” built-in function. The reason is well explained here and here.

del

del“ is a statement, not a built-in function. This post explains why it’s useful.

What is the difference between an expression and a statement?

From here.

Expressions only contain identifiers, literals and operators, where operators include arithmetic and boolean operators, the function call operator “()” the subscription operator “[]” and similar, and can be reduced to some kind of “value”, which can be any Python object.

Statement, on the other hand, are everything that can make up a line (or several lines) of Python code. Note that expressions are statements as well.

In Python document, “lambda” is treated as expression.

Compound statements

From here.

1
2
3
4
5
6
7
8
compound_stmt ::=  if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| funcdef
| classdef
| decorated

Comments