473,396 Members | 1,891 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Global vs.Local [solved]

bvdet
2,851 Expert Mod 2GB
I provide shop drawings to structural steel fabricators with SDS/2 software (http://sds2.com) by Design Data (DD). I am not a programmer by education or trade and started writing scripts about 5 years ago. DD has a script interface with Python in the 3D model which is very useful in production. Part of the Python interface includes a dialog box class:
Expand|Select|Wrap|Line Numbers
  1. dlg1 = Dialog('Dialog Box Title')
Method dlg1.done() returns a dictionary. I am exporting the dictionary or list of dictionaries to disc with Pickler and importing with Unpickler to update the variables initialized in the scripts. I have been dumping everything into the global dictionary with globals().update(dd). All variables in the scripts are accessed directly - not through a dictionary. In an effort to evolve towards local variables, I reworked one script this way:
Expand|Select|Wrap|Line Numbers
  1. def run_script():
  2.     from math import sqrt, cos, ..........
  3.     from param import ............
  4.     import macrolib.pickle
  5.     ...............
  6.     # Define default values for variables
  7.     ...............
  8.     # Define functions and classes not imported
  9.     ...............
  10.     # Import defaults file and update local dictionary
  11.     if enable_default_import_export == "Enable":
  12.         dd0 = import_data(default_file_path + def_file)
  13.         if dd0:
  14.             if isinstance(dd0, types.ListType):
  15.                 for dd in dd0:
  16.                     for key, value in dd.items():
  17.                         exec "%s = %s" % (key, repr(value)) in None
  18.             elif isinstance(dd0, types.DictType):
  19.                 for key, value in dd0.items():
  20.                     exec "%s = %s" % (key, repr(value)) in None
  21.             else:
  22.                 Warning("Invalid data - Reverting to original defaults")
  23.     ## Main program loop
  24.     while 1:
  25.         ClearSelection()
  26.         # Select members
  27.  
  28.         # do other stuff as necessary
  29.         ######################################################################################################################################
  30.         ## DIALOG BOX 1 ---------------------------------------------------------------------------------------------------------------------#
  31.         ######################################################################################################################################
  32.         dlg1 = Dialog("Add stiffener plates to beam members")
  33.         dlg1.menu("print_doc", ("Yes", "No"), "No", "Print parametric script documentation only")
  34.         dlg1.tabset_begin()
  35.         dlg1.tab("General Information")
  36.         dlg1.column_group_begin()
  37.         dlg1.column(0)
  38.         if mem2 == "pick point":
  39.             dlg1.group_title("Stiffener Location Selection Method")
  40.             dlg1.menu("location_method", ("Pick Points", "Fixed Spacing"), location_method, "Method of locating stiffeners              ")
  41.             dlg1.entry("points_x_offset", dim_print(points_x_offset), "'Pick Points' member 'X' offset distance")
  42.             dlg1.group_title_end
  43.         dlg1.group_title("Single/Double, Side, Color, Grade")
  44.         dlg1.menu("no_pairs", ("Single", "Double"), no_pairs, "Single or Double Stiffeners               ")
  45.  
  46.         # more dialog box stuff
  47.         try:
  48.             dd1 = dlg1.done()
  49.         except ResponseNotOK:
  50.             break
  51.         for key, value in dd1.items():
  52.             exec "%s = %s" % (key, repr(value)) in None
  53.         ........................................
  54.         # Do what needs to be done
  55.         ........................................
  56.         Add_pls = yes_or_no("Add more full or partial depth stiffener plates to beams?")
  57.         if Add_pls == 0:
  58.             break
  59.         #### END run_script() xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  60. if __name__ == '__main__':
  61.     try:
  62.         run_script()
  63.     finally:
  64.         del run_script
  65.  
This new way seems to work well. It would be a nightmare to rework all my scripts to access values from dictionaries or from dialog box attributes. Is there a potential problem with updating the local dictionary this way or a better way to do it? I will appreciate any suggestions.
Oct 21 '06 #1
7 2319
bartonc
6,596 Expert 4TB
Isn't python a sweet language?! It is THE tool for self-taught people to learn to write well-structured code. Looking out your code, I see a well thought-out implementation that suits your needs (and you say works well). That said, here are a couple of thoughts for you to consider:

1. Python gives access to all kinds of its inner working for us to use.
I have used the exec("a = 0") trick in a large application (gui and all) without any problems. In a simpler module, this is a very cool way to avoid dict[key] referencing.
I ran some tests and found that looping
exec "%s = %s" % (key, repr(value)) in None
is equivalent to
locals().update(dict).
The latter is probably faster, but I didn't do any profiling.

2. By creating a function (and associated name-space) that lasts for the lifetime of the module, you gain two things: eliminating all the built-in stuff that's in globals() when you actually LOOK (print) at the dictionary; it's psycological only. And python may be able to lookup your variable a little quicker due to scope rules (by which, the local name-space is searched first).

3. I may go and rework my stuff after thinking about this!
Thanks for the challenge. It looks to me like you are doing great work.
Have fun!

Barton
Oct 21 '06 #2
bvdet
2,851 Expert Mod 2GB
Thanks for the positive comments! My first choice was locals().update(dict) - of course it does not work because it is read only.
I would rather program than detail steel, but I make my living detailing. It is satisfying to write a script (fun) and use it in producing shop drawings (not so fun). The productivity increase can hit me in the wallet (fun).
Detailing steel in a 3D solids model has a lot of problems that can be solved with the script interface. Example - We can add 'construction circles' in the model by selecting a center point and a radius. A 'construction circle' is a temporary object (it does not become a permanent part of the model) which displays as a circle in the user's current plane. It is useful for determining exact 3D points on the circle. Adding a construction circle by selecting 3 points in 3D space was an interesting problem. We can also add 'construction lines' by selecting 2 points in 3D. Once you get the cons circle, we usually need cons lines laid out radially from the center point and along the arc to determine the exact points for laying out model objects. I developed a class to solve the geometry as follows:
Expand|Select|Wrap|Line Numbers
  1. See my next post for the source code 
  2.  
I am not a geometry expert either, so this took a lot of time. Note the credit to Paul Bourke Geometry - Paul Bourke. Now THAT was fun!
Oct 21 '06 #3
bvdet
2,851 Expert Mod 2GB
Code for previous post:
Expand|Select|Wrap|Line Numbers
  1. """
  2. /// Plane_Intersect3D.py - Given 3 non-collinear points, define three planes and calculate the radius and center point of
  3. /// the circle connecting the points.
  4. /// Determine if a point lies on Plane 1 (defined by initial 3 non-collinear points).
  5. /// Rotate a point about an axis defined by p1 and p1 + N_uv.
  6. /// Developed by Bruce Vaughan, BV Detailing & Design, Inc. (September 2006)
  7. /// URL: www.bvdetailing.com
  8. ####
  9. from math import pi, sqrt, acos, cos, sin
  10. from point import Point
  11. class Plane3D:
  12.     def plane_def(self, p1, p2, p3):
  13.         A = p1.y*(p2.z-p3.z) + p2.y*(p3.z-p1.z) + p3.y*(p1.z-p2.z)
  14.         B = p1.z*(p2.x-p3.x) + p2.z*(p3.x-p1.x) + p3.z*(p1.x-p2.x)
  15.         C = p1.x*(p2.y-p3.y) + p2.x*(p3.y-p1.y) + p3.x*(p1.y-p2.y)
  16.         D = -(p1.x*(p2.y*p3.z-p3.y*p2.z) + p2.x*(p3.y*p1.z-p1.y*p3.z) + p3.x*(p1.y*p2.z-p2.y*p1.z))
  17.         return A, B, C, D
  18.  
  19.     def cross_product(self, p1, p2):
  20.         return Point(p1.y*p2.z - p1.z*p2.y, p1.z*p2.x - p1.x*p2.z, p1.x*p2.y - p1.y*p2.x)
  21.  
  22.     def dot_product(self, p1, p2):
  23.         return (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z)
  24.  
  25.     def __init__(self, p1, p2, p3, theta1 = 0):
  26.         if type(p1) == type(Point(0,0,0)) and type(p2) == type(Point(0,0,0)) and type(p3) == type(Point(0,0,0)):
  27.             """
  28.             /// Paul Bourke - 'Equation of a plane' (March 1989)
  29.             /// Define a plane from 3 non-collinear points
  30.             /// Ax + By + Cz + D = 0
  31.             /// The normal 'N' to the plane is the vector (A, B, C)
  32.             """
  33.             A, B, C, self.D = self.plane_def(p1, p2, p3)
  34.             self.N = Point(A, B, C)
  35.             self.N_len = round(sqrt(A*A + B*B + C*C), 6)
  36.             if self.N_len > 0.0:
  37.                 self.N_uv = Point(self.N.x/self.N_len, self.N.y/self.N_len, self.N.z/self.N_len)
  38.             else:
  39.                 self.N_uv = Point(0.0, 0.0, 0.0)
  40.             # make p1 global to class namespace
  41.             self.p1 = p1
  42.             """
  43.             /// Paul Bourke - 'Equation of a plane' (March 1989)
  44.             /// If vector N is the normal to the plane then all points 'p' on the plane satisfy the following:
  45.             /// N dot p = k where 'dot' is the dot product
  46.             /// N dot p = N.x*p.x + N.y*p.y + N.z*p.z
  47.             """
  48.             self.k = round(self.dot_product(self.N, p1), 6)             # calculation of plane constant 'k'
  49.             self.k0 = round(self.dot_product(self.N_uv, p1), 6)         # displacement of the plane from the origin
  50.             """
  51.             /// Determine vector e and unit vector e0 (p1 to p3)
  52.             /// Determine vector d and unit vector d0 (p1 to p2)
  53.             /// Determine location of point F, midpoint on vector d
  54.             /// Determine location of point G, midpoint on vector e
  55.             """
  56.             e = p3 - p1
  57.             e_len = (sqrt(e.x**2 + e.y**2 + e.z**2))
  58.             if e_len > 0.0:
  59.                 self.e0 = Point(e.x/e_len, e.y/e_len, e.z/e_len)
  60.             else:
  61.                 self.e0 = Point(0.0, 0.0, 0.0)
  62.             d = p2 - p1
  63.             d_len = (sqrt(d.x**2 + d.y**2 + d.z**2))
  64.             if d_len > 0.0:
  65.                 self.d0 = Point(d.x/d_len, d.y/d_len, d.z/d_len)
  66.             else:
  67.                 self.d0 = Point(0.0, 0.0, 0.0) 
  68.             self.F = Point(p1.x + (d.x/2), p1.y + (d.y/2), p1.z + (d.z/2))
  69.             self.G = Point(p1.x + (e.x/2), p1.y + (e.y/2), p1.z + (e.z/2))
  70.             # Make variables 'e' and 'd' available as attributes
  71.             self.e = e
  72.             self.d = d
  73.  
  74.             # Calculate distance between points p1 and p2
  75.             self.Ra = p2.dist(p1)
  76.  
  77.             """
  78.             /// Calculate net angle between vectors d0 and e0 (Q)
  79.             /// Radius = self.Ra
  80.             /// Calculate point to point distance (pp)
  81.             """
  82.             if abs(theta1) == pi:
  83.                 self.Q = theta1
  84.             else:
  85.                 self.Q = acos(self.dot_product(self.d0, self.e0))   # radians
  86.             self.pp = abs(self.Q * self.Ra)            
  87.  
  88.         else:
  89.             raise TypeError, 'The arguments passed to Plane3D must be a POINT'
  90.  
  91.     # Calculate points to define plane #2 and calculate N2 and c2
  92.     def plane_2(self):
  93.         p1 = self.G
  94.         p2 = self.G + self.N_uv
  95.         p3 = self.G + self.cross_product(self.e0, self.N_uv)
  96.         A, B, C, D = self.plane_def(p1, p2, p3)
  97.         d = round(sqrt(A*A + B*B + C*C), 6) 
  98.         self.N2 = Point(A/d, B/d, C/d)
  99.         self.c2 = round(self.N2.x*p1.x + self.N2.y*p1.y + self.N2.z*p1.z, 6)
  100.  
  101.     # Calculate points to define plane #3 and calculate N3 and c3
  102.     def plane_3(self):
  103.         p1 = self.F
  104.         p2 = self.F + self.N_uv
  105.         p3 = self.F + self.cross_product(self.d0, self.N_uv)
  106.         A, B, C, D = self.plane_def(p1, p2, p3)
  107.         d = round(sqrt(A*A + B*B + C*C), 6)
  108.         self.N3 = Point(A/d, B/d, C/d)
  109.         self.c3 = round(self.N3.x*p1.x + self.N3.y*p1.y + self.N3.z*p1.z, 6)
  110.  
  111.     def three_pt_circle (self):     
  112.         """
  113.         /// Paul Bourke - 'Intersection of three planes' (October 2001)
  114.         /// The intersection of three planes is either a point, a line, or there is no intersection.
  115.         /// Three planes can be written as:
  116.         /// N1 dot p = c1
  117.         /// N2 dot p = c2
  118.         /// N3 dot p = c3
  119.         /// 'Nx' is the normal vector
  120.         /// 'p' is a point on the plane
  121.         /// 'dot' signifies the dot product of 'Nx' and 'p'
  122.         /// 'cx' = plane constant (displacement of the plane from the origin if Nx is a unit vector)
  123.         /// The intersection point of the three planes "M" is given by:
  124.         /// M = (c1*(N2 cross N3) + c2(N3 cross N1) + c3*(N1 cross N2)) / (N1 dot (N2 cross N3))
  125.         /// 'cross' indicates the cross product and 'dot' indicates the dot product
  126.         /// Calculate the center point of the circle (intersection point of three planes) and the radius.
  127.         /// Plane 1 is defined by the three points initially passed to class object.
  128.         """
  129.         # Define Plane 2
  130.         self.plane_2()
  131.         # Define Plane 3
  132.         self.plane_3()
  133.  
  134.         N23 = self.cross_product(self.N2, self.N3)
  135.         N31 = self.cross_product(self.N3, self.N)
  136.         N12 = self.cross_product(self.N, self.N2)
  137.         NdN23 = round(self.dot_product(self.N, N23), 6)
  138.  
  139.         numer = Point(self.k*N23.x, self.k*N23.y, self.k*N23.z) + (self.c2*N31.x, self.c2*N31.y, self.c2*N31.z) + \
  140.                      (self.c3*N12.x, self.c3*N12.y, self.c3*N12.z)
  141.         if NdN23 != 0.0:
  142.             self.M = Point(numer.x/NdN23, numer.y/NdN23, numer.z/NdN23)
  143.             self.R = self.M.dist(self.p1)
  144.         else:
  145.             self.M = Point(0.0, 0.0, 0.0)
  146.             self.R = 0.0
  147.  
  148.     """
  149.     /// Credit Paul Bourke for 'Rotate A Point About An Arbitrary Axis (3D)' (August 2002)
  150.     /// Rotate point p about a line passing through self.p1 and normal to the current plane by the angle 'theta' in radians
  151.     /// Return the new point
  152.     """    
  153.     def PointRotate3D(self, p, theta):
  154.         q2 = Point(0.0,0.0,0.0)
  155.  
  156.         # step 1 - translate space so that the rotation axis passes through the origin
  157.         q1 = p - self.p1
  158.         u = self.N_uv
  159.         d = sqrt(u.y*u.y + u.z*u.z)
  160.  
  161.         # step 2 - rotate space about the x axis so that the rotation axis lies in the xz plane
  162.         if d != 0.0:
  163.             q2.x = q1.x
  164.             q2.y = q1.y*u.z/d - q1.z*u.y/d
  165.             q2.z = q1.y*u.y/d + q1.z*u.z/d
  166.         else:
  167.             q2 = q1
  168.  
  169.         # step 3 - rotate space about the y axis so that the rotation axis lies along the positive z axis
  170.         q1.x = q2.x*d - q2.z*u.x
  171.         q1.y = q2.y
  172.         q1.z = q2.x*u.x + q2.z*d
  173.  
  174.         # step 4 - rotate about the z axis
  175.         q2.x = q1.x*cos(theta) - q1.y*sin(theta)
  176.         q2.y = q1.x*sin(theta) + q1.y*cos(theta)
  177.         q2.z = q1.z
  178.  
  179.         # inverse of step 3
  180.         q1.x = q2.x*d + q2.z*u.x
  181.         q1.y = q2.y
  182.         q1.z = -q2.x*u.x + q2.z*d
  183.  
  184.         # inverse of step 2
  185.         if d != 0.0:
  186.             q2.x = q1.x
  187.             q2.y = q1.y*u.z/d + q1.z*u.y/d
  188.             q2.z = -q1.y*u.y/d + q1.z*u.z/d
  189.         else:
  190.             q2 = q1  
  191.  
  192.         # inverse of step 1        
  193.         q1 = q2 + self.p1        
  194.  
  195.         # return rotated point
  196.         return q1            
  197.  
  198.     def lie_check(self, p4):
  199.         """
  200.         /// Paul Bourke - 'Equation of a plane' (March 1989)
  201.         /// Given any point 'a' on a plane: N dot (a-p) = 0
  202.         """
  203.         return round((self.N.x*(p4.x-self.p1.x) + self.N.y*(p4.y-self.p1.y) + self.N.z*(p4.z-self.p1.z)), 4)
  204.  
  205.     def lie_check2(self, p5):
  206.         """
  207.         /// Paul Bourke - 'Equation of a plane' (March 1989)
  208.         /// s = A*p5.x + B*p5.y + C*p5.z + D 
  209.         /// If s > 0, point p5 lies on the same side as self.N
  210.         /// If s < 0, point p5 lies on the oppsite side from self.N
  211.         /// If s = 0, point p5 lies on the plane
  212.         """
  213.         return round((self.N.x*p5.x + self.N.y*p5.y + self.N.z*p5.z + self.D), 4)
Oct 21 '06 #4
bartonc
6,596 Expert 4TB
Thanks for the positive comments! My first choice was locals().update(dict) - of course it does not work because it is read only.
I don't understand the "read only" thing. In version 2.4 a module with the following code works. What version of python are you running?
Expand|Select|Wrap|Line Numbers
  1. def test():
  2.     print "in test()"
  3.     locals().update({"a":0})
  4.     print locals()
  5.     print globals()
  6. test()
  7. print "module name-space"
  8. print locals()
  9. print globals()
  10.  
Oct 21 '06 #5
bvdet
2,851 Expert Mod 2GB
I don't understand the "read only" thing. In version 2.4 a module with the following code works. What version of python are you running?
Expand|Select|Wrap|Line Numbers
  1. def test():
  2.     print "in test()"
  3.     locals().update({"a":0})
  4.     print locals()
  5.     print globals()
  6. test()
  7. print "module name-space"
  8. print locals()
  9. print globals()
  10.  
Version 2.3 is installed with each installation of SDS/2. Believe me, I tried and tried but locals().update(dd) would not work for my application. Try this:
Expand|Select|Wrap|Line Numbers
  1. def test():
  2.         a = 10
  3.     print "in test()"
  4.     locals().update({"a":0})
  5.     print locals()
  6.     print globals()
  7. test()
  8.  
Does 'a' update to 10?
Oct 21 '06 #6
bvdet
2,851 Expert Mod 2GB
Sorry, I meant update from 10 to 0.
Oct 22 '06 #7
bartonc
6,596 Expert 4TB
Sorry, I meant update from 10 to 0.
Nope, it doesn't update. I did find this, which I didn't expect.

locals()Update and return a dictionary representing the current local symbol table. Warning: The contents of this dictionary should not be modified; changes may not affect the values of local variables used by the interpreter.

So exec() IS the legal way of changing this dict.
Oct 22 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: David Hitillambeau | last post by:
Hi guys, As I am new to Python, i was wondering how to declare and use global variables. Suppose i have the following structure in the same module (same file): def foo: <instructions>...
12
by: John M | last post by:
Hello, On Microsoft Visual Studio .NET 2003, I want to use some global elements, that can be used in each one of my pages. i.e I put a oleDBConnection on global.asax.vb How can I use it...
7
by: Ankit Aneja | last post by:
I put the code for url rewrite in my Application_BeginRequest on global.ascx some .aspx pages are in root ,some in folder named admin and some in folder named user aspx pages which are in user...
10
by: m.epper | last post by:
Hi to everybody. First of all sorry for my english, I'm italian. How can I execute a portion of code, in a function, into the global scope? Example: <?php
9
by: Ed Jensen | last post by:
I'm having a vexing problem with global variables in Python. Please consider the following Python code: #! /usr/bin/env python def tiny(): bar = for tmp in foo: bar.append(tmp) foo = bar
2
by: Florian Lindner | last post by:
Hello, I have a little problem with the global statement. def executeSQL(sql, *args): try: import pdb; pdb.set_trace() cursor = db.cursor() # db is <type 'NoneType'>. except: print...
1
weaknessforcats
by: weaknessforcats | last post by:
C++: The Case Against Global Variables Summary This article explores the negative ramifications of using global variables. The use of global variables is such a problem that C++ architects have...
112
by: istillshine | last post by:
When I control if I print messages, I usually use a global variable "int silent". When I set "-silent" flag in my command line parameters, I set silent = 1 in my main.c. I have many functions...
4
by: raylopez99 | last post by:
Why is the same variable local inside a 'foreach' loop yet 'global' in scope (or to the class) outside it? RL class MyClass { int MyMemberArray1; //member variables, arrays, that are...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.