Top | Previous | Next |
Scope and Import |
The concept of scope is very important in all programming, and Python is no exception. Scope defines what names are directly accessible without any qualifiers. Another way to put this is that the scope determines what variables are defined.
Definition by Assignment In Python, a variable is defined at the time that it is assigned. What scope it belongs to is also defined by where the assignment occurs.
doSomeWork() # on this line, there is no variable 'x' in scope
x = 5 # now 'x' is defined in our scope, because we've assigned a value to it
print x # This will work just fine, because x is in scope.
Function Scope When you define a function, that function gets its own scope. Variables that are assigned within that function body will not be available outside of the function.
def myFunction(): x = 15 # x is local to myFunction() print x # This will work, because it is part of the function
y = x + 10 # This will fail, because x is not available in the outer scope
Module or "global" scope Note: The definition of global described in this section is as of Ignition 7.7.0. Prior to this version, Ignition used different scoping rules. See the section below about Legacy Scoping.
There are lots of places to write Python code in Ignition. In Python terminology, each of these spots is called a 'module'. If you're reading Python guides, you'll also see them called 'files', because if you were outside of Ignition, these would be *.py files.
Variables defined in a module are implicitly global. This means that sub functions may reference them, as long as the sub function does not also define a variable of the same name through assignment. There is a special keyword, global, that can be used within a function to let Python know that you're trying to reference the module-scoped version of a variable, and not create a private local variable.
Consider the following example module
x = 'hello'
def foo(): print x
def bar(): x = 'nope'
def baz(): global x x = 'world'
foo() # will print 'hello' bar() # does nothing, because x inside of bar() is local foo() # will print 'hello' again baz() # re-assigns x foo() # will print 'world'
Note that the term 'global' here is somewhat misleading. Unlike in previous version of Ignition, variables marked global are not shared with other scripts. They are only global within the module that you're editing. Using the import keyword You can import the namespaces defined in other scopes into your scope with the import keyword. Most commonly, you'll import from global library sources, like system (the Ignition standard libraries), project (your project's script library), java (importing from the Java standard library), and the various python standard libraries. When you're writing component event handlers, system, shared, and project are imported for you automatically.
The import keyword can be used in a variety of forms:
For example, suppose you wanted to use the java.util.Calendar class for some date manipulations. You could import this in a number of different ways. These examples are equivalent, printing out a date 8 hours before the current date.
import java cal = java.util.Calendar.getInstance() cal.add(java.util.Calendar.HOUR, -8) print cal.getTime()
from java.util import Calendar cal = Calendar.getInstance() cal.add(Calendar.HOUR, -8) print cal.getTime()
Legacy Scoping In Ignition version 7.6 and prior, the scoping rules regarding the global keyword were different. In these versions, variables marked global were accessible from all scripts in the system. Also, module scope did not work the same way. Examples like this would not work
x = 5 def foo(): print x
and instead had to be written like this:
x = 5 def foo(x=x): print x
Legacy scripting modules (app.*) continue to run under the old scoping rules for backwards compatibility purposes. Their replacements (shared.* and project.*) run under the new scoping rules. Other scripts such as component event scripts let the user pick which scoping rules to use. To recap, the choices are:
If you have a project with mixed scope rules, you may have a need to access a legacy style global variable from a standard style script. To do this, you can use the system.util.getGlobals() method, which returns the global namespace as a dictionary. This provides access to the legacy style of global variables. |