1.11M Members

Starting Python

 
0
 

Well how about getting each details out.
friends = {
'Fred' : {'city' : 'Pasadena', 'age' : 45},
'Adam' : {'city' : 'Dallas', 'age' : 27},
'Lisa' : {'city' : 'Chicago', 'age' : 31},
'Ulla' : {'city' : 'Las Vegas', 'age' : 19},
'Mark' : {'city' : 'New York', 'age' : 24}
}

print "Name %20s %5s"%("City","Age")  
print "="*38
for x in sorted(friends):
	print "%s  Details are %s "%(x, [ y for y in friends[x].values()])  

----output--------
Name                 City   Age
======================================
Adam  Details are ['Dallas', 27] 
Fred  Details are ['Pasadena', 45] 
Lisa  Details are ['Chicago', 31] 
Mark  Details are ['New York', 24] 
Ulla  Details are ['Las Vegas', 19]

from my htc phone

 
0
 

I would prefer this:

friends = {
'Fred' : {'city' : 'Pasadena', 'age' : 45},
'Adam' : {'city' : 'Dallas', 'age' : 27},
'Lisa' : {'city' : 'Chicago', 'age' : 31},
'Ulla' : {'city' : 'Las Vegas', 'age' : 19},
'Mark' : {'city' : 'New York', 'age' : 24}
}
for x in sorted(friends):
    print("Friend {name:>6}  is living in {friend[city]:>10} and is now {friend[age]:3} years old.".format(
                 friend=friends[x], name = x))

Output:

Friend   Adam  is living in     Dallas and is now  27 years old.
Friend   Fred  is living in   Pasadena and is now  45 years old.
Friend   Lisa  is living in    Chicago and is now  31 years old.
Friend   Mark  is living in   New York and is now  24 years old.
Friend   Ulla  is living in  Las Vegas and is now  19 years old.

Works even with Python 2.6.6

 
3
 

Now to something less nit-picky:

# create an accumulator decorator using a class

class Accum(object):
    """
    a decorator class that shows the number
    of times a decorated function is called
    """
    def __init__(self, func):
        self.calls = 0
        self.func = func

    def __call__(self, *args, **kwargs):
        self.calls += 1
        print( 'call %s to %s' % (self.calls, self.func.__name__) )
        # now run the decorated function ...
        self.func(*args, **kwargs)


# implement the decorator for function funcx this way
@Accum
def funcx(a, b, c):
    print( a, b, c )

funcx(11, 12, 13)
funcx('fat', 'bat', 'cat')

"""my result with Python32 -->
call 1 to funcx
11 12 13
call 2 to funcx
fat bat cat
"""
 
0
 

The ordered dictionary container maintains a doubly-linked list of keys, appending new keys to the list as they're inserted. A secondary dictionary maps keys to their corresponding list node, so deletion doesn't have to traverse the entire linked list:

# new in Python 2.7 and Python3

from collections import OrderedDict

d = dict((chr(64+x), x) for x in range(1, 6))
print("a regular dictionary has keys in hash order:")
print(d)
od = OrderedDict((chr(64+x), x) for x in range(1, 6))
print("an ordered dictionary has keys in creation order:")
print(od)

"""my output -->
a regular dictionary has keys in hash order:
{'A': 1, 'C': 3, 'B': 2, 'E': 5, 'D': 4}
an ordered dictionary has keys in creation order:
OrderedDict([('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5)])
"""

# an ordered dictionary can be used similar to a regular dictionary
print("od.items() = %s" % od.items())
print("od.keys() = %s" % od.keys())
print("od.values() = %s" % od.values())
print("value of key 'D' = %s" % od['D'])
# change vlaue at key 'D'
od['D'] = 99
print("changed value of key 'D' = %s" % od['D'])

"""my output -->
od.items() = [('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5)]
od.keys() = ['A', 'B', 'C', 'D', 'E']
od.values() = [1, 2, 3, 4, 5]
value of key 'D' = 4
changed value of key 'D' = 99
"""
 
1
 

Explore what you can do with function memoryview()

# testing memoryview()
# Python 2.7

mv = memoryview('abcdefg')

print(mv)  # <memory at 0x01DB4E40>

print(len(mv))  # 7
# item at index 1
print(mv[1])  # b
# show bytes in mv
print(mv.tobytes())  # abcdefg
# show ordinals
print(mv.tolist())  # [97, 98, 99, 100, 101, 102, 103]
 
0
 

A look at the new Python module fractions (new with Python27 and Python3):

# Python27 can calculate with fractions
# this avoids the inaccuracies associated with floating point numbers

from fractions import Fraction
import math

# Fraction(numerator, denominator)
# fraction 2/3 would be Fraction(2, 3)
a = Fraction(2, 3)
# fraction 2/5 would be Fraction(2, 5)
b = Fraction(2, 5)

# calculate with fractions
# for instance (2/3) + (2/5) --> 16/15
addition = a + b
print(addition)   # 16/15

# fraction has its own type
print(type(addition))  # <class 'fractions.Fraction'>

# obtain a fraction close to pi
pi_s = str(math.pi)
lim = 1000
pi_f = Fraction(pi_s).limit_denominator(lim)
print(pi_f)    # 355/113
 
0
 

Exploring strings with Python:

# using function zip() with strings

a = 'abcdef'
b = 'ghijklmnopq'

# only goes the length of the shortest string
print(list(zip(a, b)))

""" my output -->
[('a', 'g'), ('b', 'h'), ('c', 'i'), ('d', 'j'), ('e', 'k'), ('f', 'l')]
"""
 
0
 

A look at the new Python module fractions (new with Python27 and

Just to fix the data, from 2.7.1 documentation:

9.5. fractions — Rational numbers
New in version 2.6.

 
1
 

A trick to create a lot of sequential variable names:

# use the Python local dictionary to create
# variables qq1 to qq7 and initializes them to 99

for n in range(1, 8):
    # create the variable name
    # for instance "qq" + "3" gives "qq3"
    var_name = "qq" + str(n)
    # give it the value 99
    locals()[var_name] = 99

# testing
print(qq1)
print(qq3)

print('-'*9)

for k, v in sorted(locals().items()):
    if 'qq' in k:
        print("%s = %s" % (k, v))

""" my output -->
99
99
---------
qq1 = 99
qq2 = 99
qq3 = 99
qq4 = 99
qq5 = 99
qq6 = 99
qq7 = 99
"""
 
1
 

A trick to create a lot of sequential variable names:

Trick -> alarm bells

Tricks are generally frowned in Python circles. It is difficult to find good place for many variables for which we have to know names to use them, instead of using sequential data structure like list or tuple.

 
3
 

This shows you how to compress and decompress a typical text file using Python module gzip ...

# using module gzip to compress and decompress files
# default compression level is 9 (out of 1-9)
# needs Python27 or higher
# tested with Python27 and Python32  by vegaseat

import gzip

txt_file = "Edictionary.txt"
gz_file = "Edictionary.gz"

# reads in a 747kb .txt file, compresses to a 201kb .gz file
# mode='rb' is needed for the text file
with open(txt_file, 'rb') as f_in:
    with gzip.open(gz_file, 'wb') as f_out:
        f_out.writelines(f_in)

print("Read .gz file in as one string ..")
with gzip.open(gz_file, 'rb') as f:
    # decode <class 'bytes'> to string
    # .decode("utf8") does not work here
    text2 = f.read().decode("latin1")

print("Show first 80 characters:")
print(text2[:80])

print('-'*37)

# a mildly different approach using the class
print("Read .gz file in as list of lines ...")
gzin = gzip.GzipFile(gz_file, 'rb')
lines = gzin.readlines()
gzin.close()

print("Show first 10 lines:")
for line in lines[:10]:
    # decode <class 'bytes'> to string
    line = line.decode("latin1").rstrip()
    print(line)

'''result ...
Read .gz file in as one string ..
Show first 80 characters:
Aachen
aardvark
aardvarks
aaron
abaci
aback
abacus
abacuses
abaft
abalo
-------------------------------------
Read .gz file in as list of lines ...
Show first 10 lines:
Aachen
aardvark
aardvarks
aaron
abaci
aback
abacus
abacuses
abaft
abalone
'''
Attachments Edictionary.txt (746.51KB)
 
4
 

Python comes with module sqlite3 to create and process databases that can be queried with its common query language. First, let's create a database file ...

# explore Python module sqlite3
# create a database file
# the query language is in optional upper case
# using unique id numbers prevents appending an existing db file 
# tested with Python27 and Python32

import sqlite3

# create/connect to a permanent database file
file_name = "stock_portfolio2.db3"
con = sqlite3.connect(file_name)

# establish the cursor
cur = con.cursor()

# if it doesn't exist yet, create the table named stocks
# give each transaction a unique id number
cur.execute('''CREATE TABLE IF NOT EXISTS stocks
    (id INT PRIMARY KEY, date TEXT, trans TEXT, 
    symbol TEXT, qty REAL, price REAL)''')

# insert several lines at once using a
# list of (id, date, trans, symbol, qty, price) tuples
# each tranaction is given a unique id for data security
# the unique id primary key prevents any existing database file
# from being appended with a potentially conflicting data id 
try:
    stocks = [
    (100, '2011-05-07', 'buy', 'AZN', 500, 55.05),
    (101, '2011-05-07', 'buy', 'CAT', 200, 110.34),
    (102, '2011-05-07', 'sell', 'IBM', 100, 168.89),
    (103, '2011-05-07', 'buy', 'GE', 2000, 20.01)
    ]
    # the ? placeholders match tuple items
    cur.executemany("""INSERT INTO stocks
    VALUES (?, ?, ?, ?, ?, ?)""", stocks)
except:
    pass

# commit current data to the db file
con.commit()

# quickly test the database, in sorted order by symbol
cur.execute('SELECT * FROM stocks ORDER BY symbol')
# fetch all data rows
for row in cur.fetchall():
    print(row)

'''
(100, u'2011-05-07', u'buy', u'AZN', 500.0, 55.05)
(101, u'2011-05-07', u'buy', u'CAT', 200.0, 110.34)
(103, u'2011-05-07', u'buy', u'GE', 2000.0, 20.01)
(102, u'2011-05-07', u'sell', u'IBM', 100.0, 168.89)
'''

# done
con.close()

Now let's use the database file we just created ...

# explore Python module sqlite3
# read an existing database file
# query language in upper case (optional)
# tested with Python27 and Python32

import sqlite3

# connect to the permanent database file
file_name = "stock_portfolio2.db3"
con = sqlite3.connect(file_name)

# establish the cursor
cur = con.cursor()

# use cursor method execute() to test the database
cur.execute('SELECT * FROM stocks')
col_name_list = [tup[0] for tup in cur.description]
print("Table header:")
print(col_name_list)

'''
Table header:
['id', 'date', 'trans', 'symbol', 'qty', 'price']
'''

print('-'*50)

cur.execute('SELECT * FROM stocks')
# fetch first data row
row = cur.fetchone()
print(row)

'''result Python32 ...
(100, '2011-05-07', 'buy', 'AZN', 500.0, 55.05)
'''

print('-'*50)

cur.execute('SELECT id FROM stocks')
# fetch id numbers of all data rows
for row in cur.fetchall():
    print(row)

'''
(100,)
(101,)
(102,)
(103,)
'''

print('-'*50)

cur.execute('SELECT trans, qty, symbol, date FROM stocks')
# fetch selected items of all data rows
for row in cur.fetchall():
    print("%s %s %s on %s" % row)

'''
buy 500.0 AZN on 2011-05-07
buy 200.0 CAT on 2011-05-07
sell 100.0 IBM on 2011-05-07
buy 2000.0 GE on 2011-05-07
'''

# done
con.close()

I hope you can dream up a better example of a database.

 
2
 

The Python module shelve is used to make a dictionary persistent:

# use a Python dictionary and module shelve
# to create a 'persistent to file' dictionary
# Python2 creates a single (24kb) file 'my_shelve.slv'
# Python3 creates 3 much smaller (1kb) files:
# "my_shelve.slv.dir"
# "my_shelve.slv.dat"
# "my_shelve.slv.bak"

import shelve
import pprint

# name shelve byte stream data file
data_file = "my_shelve.slv"

# save a python dictionary object to a file
# access key will be string 'comp_d'
sh = shelve.open(data_file)
# this will save to the file automatically
sh['comp_d'] = {'upgrade': 'steep hill', 'chip': 'munchies for TV'}

sh.close()

# retrieve the python dictionary object from the file
# use correct access key 'comp_d'
sh = shelve.open(data_file)
dc = sh['comp_d']

# then add additional data
dc['cursor'] = 'someone who swears'
# add to shelve via access key 'comp_d'
# this will update the file too
sh['comp_d'] = dc

sh.close()

# retrieve the updated dictionary from the file and display
sh = shelve.open(data_file)
pprint.pprint(sh['comp_d'])
sh.close()

""" my output -->
{'chip': 'munchies for TV',
 'cursor': 'someone who swears',
 'upgrade': 'steep hill'}
"""
 
2
 

Here we use the module matplotlib to plot a histogram (bar chart) of characters 'a' through 'z' as they appear in a given text ...

# create a list of [char,freq] lists of a text
# the plotting part needs the matplotlib module
# from
# http://sourceforge.net/projects/matplotlib/files/matplotlib/
# Windows installer matplotlib-1.0.1.win32-py2.7.exe
# or for Python32 use
# Windows installer matplotlib-1.1.0.dev.win32-py3.2.exe
# from
# http://www.lfd.uci.edu/~gohlke/pythonlibs/
# tested with Python27 and Python32  by  vegaseat

# use pylab namespace for clarity
import matplotlib.pylab as pylab

# just a simple text for testing
text = """\
Mississippi
"""

alpha = 'abcdefghijklmnopqrstuvwxyz'
# create initial list of [char,freq] lists
# of all lower case characters and freq=0
alpha_freq = [[c, 0]  for c in alpha]

print(alpha_freq)  # test
print('-'*60)

# increment the freq of a given character
for c in text.lower():
    if c in alpha:
        ix = alpha.index(c)
        alpha_freq[ix][1] += 1
        
print(alpha_freq)  # test
print('-'*60)

# use alpha_freq list to plot a char, freq histogram 
# using the matplotlib module's pylab
fig = pylab.figure()
ax = fig.add_subplot(111)
# data points ...
heights = [freq for c, freq in alpha_freq]
values = range(len(alpha))
# draw a matlib bar chart
pylab.bar (values, heights)
pylab.grid (True)
pylab.title ('Letter frequency in a text')
pylab.xlabel ('char a-z')
ax.set_xticks(values)
ax.set_xticklabels(tuple(alpha))
pylab.ylabel ('counts')

pylab.show()
 
1
 

A simpler matplotlib example ...

# plotting with the pylab module from matplotlib
# http://sourceforge.net/projects/matplotlib/files/matplotlib/
# used Windows installer matplotlib-1.0.1.win32-py2.7.exe
# modified Ene's code, tested with Python27

import math
import matplotlib.pylab as pylab

# create the x list data
# arange() is just like range() but allows float numbers
# actually uses numpy's arange()
#
x_list = pylab.arange(0.0, 5.0, 0.01)

# calculate the y list data
#
y_list = []
for x in x_list:
    # give it some fancy decaying function
    y = math.cos(2*math.pi*x) * math.exp(-x)
    y_list.append(y)

pylab.xlabel("x")
pylab.ylabel("cos(2pi * x) * exp(-x)")

# draw the plot with a blue line 'b' (default)
# using x,y data from the x_list and y_list
#
# other drawing styles -->
# 'r' red line, 'g' green line, 'y' yellow line
# 'ro' red dots, 'r.' smaller red dots, 'r+' red pluses
# 'r--' red dashed line, 'g^' green triangles, 'bs' blue squares
# 'rp' red pentagons, 'r1', 'r2', 'r3', 'r4' just check them out
#
pylab.plot(x_list, y_list, 'b')

# optionally save the plot as a .png image file
pylab.savefig('pylab_fancy.png')

# show the pylab plotting window
# zoom the graph, drag the graph, change the margins, save the graph
pylab.show()
 
1
 

Something simple, but handy at times ...

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    bs = ''
    for x in range(0, bits):
        if 2**x == 2**x & num:
            bs = '1' + bs
        else:
            bs = '0' + bs
    return bs

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011
 
0
 

Something simple, but handy at times ...

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    bs = ''
    for x in range(0, bits):
        if 2**x == 2**x & num:
            bs = '1' + bs
        else:
            bs = '0' + bs
    return bs

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011

Darn. getting those post duplicates again!

 
1
 

If you have Python 2.7 or higher, vegaseat's approach can be simplified:

# with Python27+ you can use the following scheme for padding
# binary numbers with leading zeros

print(bin(255))                     # 0b11111111
print(bin(255)[2:])                 # 11111111
print(bin(255)[2:].rjust(12, '0'))  # 000011111111

print(bin(76)[2:].rjust(8, '0'))    # 01001100

Or putting it all into one nice function:

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    needs Python27 or higher
    """
    return bin(num)[2:].rjust(bits, '0')

# test
print(int2binpad(255, 12))  # 000011111111
print(int2binpad(254, 12))  # 000011111110
print(int2binpad(76, 8))    # 01001100
print(int2binpad(3))        # 0011

# stressing the function one little, seems to behave
print(int2binpad(76))       # 1001100
 
2
 

Vegaseat surely knows that way, but sometimes people are required not to use bin function but wrap one of their own. If you want to shrink the vegas eater funcition's code to one line it is possible with join and character generator:

# convert an integer number to its binary representation
# and pad the result with a specified number of leading zeros
# tested with Python27 and Python32  by  vegaseat

def int2binpad(num, bits=4):
    """
    returns the binary of integer num, using bits
    number of digits, will pad with leading zeros
    """
    return ''.join('0' if int(num & (2 ** x) > 0) else '1'  for x in reversed(range(0, bits)))

# testing ...
if __name__ == '__main__':
    print(int2binpad(255, 12))  # 000011111111
    print(int2binpad(254, 12))  # 000011111110
    print(int2binpad(76, 8))    # 01001100
    print(int2binpad(3))        # 0011

More traditional style is of course to do division by base and collect modulos in reverse to do generalized version of base change.

 
2
 

If you wan to get numeric input, optionally within a range of values, you can use the Tkinter GUI toolkit (comes with your Python installation) and its small pop-up dialogs in a console program ...

# use Tkinter's simple dialogs (pop-up) to ask for input
# minvalue and maxvalue are optional

try:
    # for Python2
    import Tkinter as tk
    import tkSimpleDialog as tksd
except ImportError:
    # for Python3
    import tkinter as tk
    import tkinter.simpledialog as tksd

root = tk.Tk()
# show input dialogs without the Tkinter window
root.withdraw()

# if a non-numeric value is entered, will prompt again
price = tksd.askfloat("Price", "Enter the price of the item:")
print(price)
# use askfloat or askinteger (whole items only)
quantity = tksd.askinteger("Quantity", "Number of items needed:",
    minvalue=1, maxvalue=1000)
print(quantity)

result = "Total cost is %0.2f" % (price*quantity)
print(result)

# you could even use askstring() to display the result
sf = "%0.2f" % (price*quantity)
tksd.askstring("Result", "Total cost is:", initialvalue=sf)
Isn't it about time forums rewarded their contributors?

Earn rewards points for helping others. Gain kudos. Cash out. Get better answers yourself.

It's as simple as contributing editorial or replying to discussions labeled or OP Kudos

You
This is an OP Kudos discussion and contributors may be rewarded
Post:
Start New Discussion
View similar articles that have also been tagged: