• D8628c48564730f602221251465aa503?s=80&d=mm

    Scope obscura

    shubb - over 5 years ago (Dec 02, 2013, 7:02 PM)
    I added some stuff about scope, which I found really useful for having a proper feel of what python was going to do...
  • Changes have been accepted Merged
      Looks like something's not quite right here.. We've been notified of the issue, and will get back to you soon.
      document

      # **Python Essential Reference**

      ## **Print Stuff**
      1. print year, principal
      2. print "%3d %0.2f" % (year, principal)
      3. print format(year,"3d"),format(principal,"0.2f")
      4. print "{0:3d} {1:0.2f}".format(year,principal)


      ## **File**
      - Read File:
      f = open("foo.txt") # Returns a file object
      line = f.readline() # Invokes readline() method on file
      while line:
      print line, # trailing ',' omits newline character
      print(line,end='') # Use in Python 3
      line = f.readline()
      f.close()

      - Write File:
      1. f = open("out","w") # Open file for writing
      while year <= numyears:
      principal = principal * (1 + rate)
      print >>f,"%3d %0.2f" % (year,principal)
      //f.write("%3d %0.2f¶
      " % (year,principal))
      year += 1
      f.close()
      2. import sys
      sys.stdout.write("Enter your name :")
      name = sys.stdin.readline()
      3. name = raw_input("Enter your name :")


      - Triple-quoted strings are useful when the contents of a string literal span multiple lines of text

      - Strings are stored as sequences of characters indexed by integers, starting at zero.

      - Although str() and repr() both create strings, their output is usually slightly different.
      str() produces the output that you get when you use the print statement,
      whereas repr() creates a string that you type into a program to exactly represent the
      value of an object. For example:
      >>> x = 3.4
      >>> str(x)
      '3.4'
      >>> repr(x)
      '3.3999999999999999'

      ## **List** []
      import sys # Load the sys module
      if len(sys.argv) != 2 # Check number of command line arguments :
      print "Please supply a filename"
      raise SystemExit(1)
      f = open(sys.argv[1]) # Filename on the command line
      lines = f.readlines() # Read all lines into a list
      f.close()
      # Convert all of the input values from strings to floats
      fvalues = [float(line) for line in lines]
      # Print min and max values
      print "The minimum value is ", min(fvalues)
      print "The maximum value is ", max(fvalues)

      - List-comprehension
      fvalues = [float(line) for line in open(sys.argv[1])]
      - min max
      min(fvalues)
      max(fvalues)


      ## **Tuples** ()
      - Python often recognizes that a tuple is intended even if the parentheses are missing:
      stock = ('GOOG', 100, 490.10)
      stock = 'GOOG', 100, 490.10

      - Some programmers are inclined to ignore tuples altogether and simply use lists because they seem to be more flexible. Although this works, it wastes memory if your program is going to create a large number of small lists (that is, each containing fewer than a dozen items).This is because lists slightly overallocate memory to optimize the performance of operations that add new items. Because tuples are immutable, they use a more compact representation where there is no extra space.

      - Use List and Tuple together:
      filename = "portfolio.csv"
      portfolio = []
      for line in open(filename):
      fields = line.split(",") # Split each line into a list
      name = fields[0] # Extract and convert individual fields
      shares = int(fields[1])
      price = float(fields[2])
      stock = (name,shares,price) # Create a tuple (name, shares, price)
      portfolio.append(stock) # Append to list of records


      ## **Sets** set()
      - Unlike lists and tuples, sets are unordered and cannot be indexed by numbers.Moreover, the elements of a set are never duplicated.
      >>> t = set("Hello")
      >>> t
      set(['H', 'e', 'l', 'o'])
      - Sets support a standard collection of operations
      a = t | s # Union of t and s
      b = t & s # Intersection of t and s
      c = t – s # Set difference (items in t, but not in s)
      d = t ^ s # Symmetric difference (items in t or s, but not both)
      - Add Update Remove
      t.add('x') # Add a single item
      s.update([10,37,42]) # Adds multiple items to s
      t.remove('H') # Removes single items from t

      ## **Dictionaries** {}






      ## **Scopes**

      In python, a variable name can be thought of as a label attatched to a variable stored in memory.

      If I go
      a = 1
      b = a
      Then both a and b point to the same reference object (which represents 1).
      If I wrote:
      a = []
      b = a
      b.append("hi")
      print a[0]
      Then the output will be "hi".

      This is important when you are dealing with mutable types, as in the list example above.

      This next part I am having trouble expressing so you will excuse me if I lead with a code sample:

      a = 5
      def doStuff(b) :
      b = b + 5
      print b
      doStuff(a)
      print a

      The output of the above is 10 and then 5

      But:

      a = []
      def doStuff(b) :
      b.append('hi')
      print b[0]
      doStuff(a)
      print a[0]

      The output of the above is 'hi' and then 'hi'.

      That is, when you call a function, the parameters, which are references, are coppied, but the values in memory they refer to are not.
      So if you re-assign the variable within the function, using the equals operator, the original label is not affected, because you didn't modify that label, you modified the new one that was created when you called the function.
      But if you modify the mutable value in memory pointed at by that label, then sure you get side effects when you return out of the function.

      A couple more interesting things about scope -

      In python, all the variables from the parent calling function are still in scope in the child function that got called. So you can go:

      def doStuff(a) :
      print b

      a = 0
      b = 5
      doStuff(b)

      and it will print 5.

      But variables declared in the function prototype 'shadow' (hide) variables that already existed, so if you go:

      a = 5
      b = 10
      def stuff(a):
      a = 15
      b = 20
      print a

      print a
      print b

      It will print 15, then 10 and then 20.
      That is, b was modified but a was not. The new variable, that shadows (hides) a got modified

      If you pass a mutable type into a function as a paramter and modify it, those modifications will still be present when you get back to the calling function.

      In general, you should not take advantage of variables from the calling function being in scope. List everything you need in the function prototype, so that if you reuse the code, the names are reliable (and so you don't have to think of the above wierdness).

      But knowing that where you modify a mutable object that you passed to a function, there is only one copy and you are modifying that is really useful.