3
# intercept a wrong data type with a function decorator

def require_numeric (func):
    """decorator to check if function argument is of type int or float"""
    def wrapper (arg1, arg2=0):
        if type(arg1) == int or type(arg1) == float:
            return func(arg1)
        else:
            print("need a numeric value!")
    return wrapper

@require_numeric
def print_num(arg):
    print("numeric value = %f" % arg)

# test ...
print_num(7.33)        # numeric value = 7.330000
print_num("$3.99")  # need a numeric value!
Votes + Comments
Kind of fun func!
0

@HIhe
Lets be functional and generate/itertools/lambda the same:

# everyone likes TGIF
# so loop through a whole year day by day and show all the dates that are Fridays
from itertools import takewhile, count
import datetime

# pick a year
year = 2012
one_day = datetime.timedelta(days=1)
start_year = datetime.date(year, 1, 1)

print("These are all the Fridays of %d:" % year)
for day in takewhile(lambda d: d <= datetime.date(year, 12, 31), (start_year + one_day * c for c in count(0))):
    if day.weekday() == 4:
        print("%s is a Friday" % day)

Edited by pyTony

1

Numpy is a high speed numeric module for Python:

# use loadtxt() to load a data file to a numpy array

try:
    # Python2
    from StringIO import StringIO
except ImportError:
    # Python3
    from io import StringIO
import numpy as np

data_str = """\
1,2,3
4,5,6
"""
# create a file object
data_file = StringIO(data_str)
# load into a numpy array, default is float datatype
data_array = np.loadtxt(data_file, delimiter=',', dtype=int)

print(data_array)

'''
[[1 2 3]
 [4 5 6]]
'''

print('-'*30)

data_str2 = """\
frank,19,167
jean,18,123
"""
# create a file object
data_file2 = StringIO(data_str2)
# load mixed data types into a numpy array
dt = {
'names': ('first','age','weight'),
'formats' : ('S12','i4','i4')
}
data_array2 = np.loadtxt(data_file2, delimiter=',', dtype=dt)

print(data_array2)

'''
python2>>>
[('frank', 19, 167) ('jean', 18, 123)]
python3>>>
[(b'frank', 19, 167) (b'jean', 18, 123)]
'''
1
# sum a bunch of numbers recursively

# works with Python2 and Python3
try:
    input = raw_input
except NameError:
    pass

def my_sum():
    n = input('Next number or blank to finish: ')
    return (float(n) + my_sum()) if n else 0

s = my_sum()
print("The sum of numbers is %s" % s)
1
# specifically replace full words only
# will replace red but not change reduce
# like the normal string.replace() function would
# note that replacement is case sensitive
# attached quotes and punctuation marks are neutral

import re

def replacer(match_obj):
    # function will be called for each key_word
    # in the text during substitution
    word = match_obj.group(0)
    return replace_dict.get(word, word)

text = """
In this text 'debug' will be changed but not 'debugger'.
Similarly red will be replaced but not reduce.
How about Fred, -red- and red?  Red, white and blue
"""

# create a dictionary of key_word:replace_with pairs
replace_dict = {
"red" : "redish",
"debug" : "fix"
}

# a regular expression matching all identifiers
pattern = re.compile(r"[A-Za-z_]\w*")

print(pattern.sub(replacer, text))

"""result -->
In this text 'fix' will be changed but not 'debugger'.
Similarly redish will be replaced but not reduce.
How about Fred, -redish- and redish?  Red, white and blue
"""
0

Time a function with a timing decorator:

# time relatively time consuming functions
# with a decorator function
# apply the decorator right above the function
# you want to time, starting with a @
# works with Python27 and Python32
# (use module timeit for faster functions)

import time

def print_timing(func):
    """set up a decorator function for timing"""
    def wrapper(*arg):
        t1 = time.time()
        res = func(*arg)
        t2 = time.time()
        print('%s took %0.3f ms' % (func.__name__, (t2-t1)*1000.0))
        return res
    return wrapper

@print_timing
def get_primes(n):
    """
    standard optimized sieve algorithm to get a list
    of prime numbers from 2 to < n, prime numbers are
    only divisible by unity and themselves
    (1 is not considered a prime number)
    """
    if n < 2:  return []
    if n == 2: return [2]
    # do only odd numbers starting at 3
    s = list(range(3, n+1, 2))
    # n**0.5 simpler than math.sqr(n)
    mroot = n ** 0.5
    half = len(s)
    i = 0
    m = 3
    while m <= mroot:
        if s[i]:
            j = (m*m-3)//2
            s[j] = 0
            while j < half:
                s[j] = 0
                j += m
        i += 1
        m = 2*i+3
    # skip all zero items in list s
    return [2]+[x for x in s if x]


print( "prime numbers from 2 to <10,000,000 using a sieve algorithm")
prime_list = get_primes(10000000)

'''my result with Python32 -->
prime numbers from 2 to <10,000,000 using a sieve algorithm
get_primes took 2632.000 ms

just a note, result with Python27 -->
get_primes took 2394.000 ms
'''
0

You can use lambda to set up a function:

# works with Python27 and Python32

# a recursive denary to binary function via lambda
d2b = lambda d: (not isinstance(d,int) or (d==0)) and '0' \
    or (d2b(d//2)+str(d%2))


den = 255
print("denary = %d" % den)
binary = d2b(den)
print("binary = %s" % binary)
# check reult with function bin()
print("binary = %s via bin(%d)" % (bin(den), den))

'''result -->
denary = 255
binary = 011111111
binary = 0b11111111 via bin(255)
'''
0

You can set up a function decorator using a class:

# using a Python class as a decorator

class StripCharacters:
    """
    a decorator class to strip given chrs from string text
    by default strip common punctuation marks --> ,.?!:;
    """
    def __init__(self, func, chrs=",.?!:;"):
        self.chrs = chrs
        self.func = func

    def __call__(self, text):
        """
        allows the class instance to be called as a function
        """
        # do the stripping
        new_text = ''.join(c for c in text if c not in self.chrs)
        return self.func(new_text)

@StripCharacters
def print_text(text):
    print(text)

text1 = 'If you are here, you are lost!'
print_text(text1)

print('-'*30)

text2 = 'common punctuation marks are ,.?!:;'
print_text(text2)

'''my result -->
If you are here you are lost
------------------------------
common punctuation marks are 
'''
0

You can use Python to check the size of a given directory (folder):

# determine the size of a given folder in MegaBytes

import os

# pick a folder you have ...
folder = r'C:\Python32\DLLs'

folder_size = 0
for (path, dirs, files) in os.walk(folder):
    for file in files:
        filename = os.path.join(path, file)
        folder_size += os.path.getsize(filename)

print("Folder %s = %0.1f MB" % (folder, folder_size/(1024*1024.0)))

'''possible result -->
Folder C:\Python32\DLLs = 5.6 MB
'''
0

Sometimes you have to flatten a deeply nested list or tuple:

# flatten a nested list

def flatten(seq):
    mylist = []
    for item in seq:
        if isinstance(item, (list, tuple)):
            # recursive function
            mylist.extend(flatten(item))
        else:
            mylist.append(item)
    return mylist

nested_list = [1, 2, [3, 4, [5, 6, [7, 8]]]]
print(nested_list)
print('nested list flattened:')
print(flatten(nested_list))

'''result-->
[1, 2, [3, 4, [5, 6, [7, 8]]]]
nested list flattened:
[1, 2, 3, 4, 5, 6, 7, 8]
'''
1

The Python function range() handles only integers. Here is a range generator that handles floats:

# a floating point range generator with roundoff-fix
# works with Python2 and Python3

def frange(start, stop=None, step=1.0, delta=0.0000001):
    """
    a range generator that handles floating point numbers
    uses delta fuzzy logic to avoid float rep errors
    eg. stop=6.4 --> 6.3999999999999986 would slip through
    """
    # if start is missing it defaults to zero
    if stop == None:
        stop = start
        start = 0
    # allow for decrement
    if step <= 0:
        while start > (stop + delta):
            yield start
            start += step
    else:
        while start < (stop - delta):
            yield start
            start += step

# testing ...
# expect numbers 6.0 to 6.3
for k in frange(6.0, 6.4, 0.1):
    print("%f" % k)

'''my result -->
6.000000
6.100000
6.200000
6.300000   okay!
'''
0

The Python function format is available for Python27 and Python3 and above ...

# create a 4 row 5 column evenly spaced table using format()
# tested with Python27 and Python32

text = """\
kamikaze pilots did wear helmets
abbreviation is a long word
shoot them in tourist season
a quarterback is a refund
"""

# create a list of the words
w = text.split()

n = 0
for k in range(0, len(w), 5):
    # Python27 and higher string formatting
    # use a field of 13 char to fit longest word
    sf = '{:13s} {:13s} {:13s} {:13s} {:13s}'    
    print(sf.format(w[n], w[n+1], w[n+2], w[n+3], w[n+4]))
    n += 5

"""
kamikaze      pilots        did           wear          helmets      
abbreviation  is            a             long          word         
shoot         them          in            tourist       season       
a             quarterback   is            a             refund    
"""
2

Use the Python module timeit to test the speed of a function. Here is an easy way:

'''get_timing.py
use Python module timeit in a wrapper
modified vegaseat code
works with Python2 and Python3
'''

def get_timing(fs, number=10000, module="__main__"):
    """
    this wrapper can be used to time any function
    pass full function call in as a string eg. 'func(arg1, arg2)'
    number = number of timeit loops
    module namespace is autodetected
    """
    import timeit
    import inspect
    # extract function name
    q1 = fs.split('(')
    f = eval(q1[0])
    # extract arguments
    q2 = q1[1].strip(')')
    if q2:
        args = eval(q2)
    else:
        args = None
    name = f.__name__
    # get module namespace
    module = inspect.getmodule(f).__name__
    if args == None:
        st1 = "%s()" % (name)
    elif type(args) == tuple:
        st1 = "%s%s" % (name, args)
    elif type(args) == str:
        st1 = "%s('%s')" % (name, args)
    else:
        st1 = "%s(%s)" % (name, args)
    st2 = "from %s import %s" % (module, name)
    t = timeit.Timer(st1, st2)
    # elapsed time is in microseconds
    print("Function %s took %.2f microseconds/pass" % \
        (st1, 1000000*t.timeit(number=number)/number))
    # optional ...
    return eval(fs)

def gcd3(x, y):
    """greatest common denominator, non-recursive"""
    while y:
        x, y = y, x % y
    return x

def test():
    pass

# testing ...
if __name__=="__main__":
    import math

    # no arguments
    print(get_timing('test()'))

    # one argument
    print(get_timing("math.log(1000)"))

    # two arguments
    print(get_timing('gcd3(1251, 3357)'))
Votes + Comments
nice
0

Create a multidimensional array (matrix or list of lists):

# create a x by y matrix (list of lists)

import pprint

def zero_matrix(x,y):
    '''create a x rows by y columns matrix of zeroes'''
    return [[0 for a in range(y)] for b in range(x)]


# test matrix has 10 rows and 12 columns
ma = zero_matrix(10, 12)
pprint.pprint(ma)

print('-'*32)

# to test change row=0 col=0 to a 1
ma[0][0] = 1
pprint.pprint(ma)

''' result -->
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
--------------------------------
[[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

'''
1

One way to display text in color:

# display a multi-line text in your browser in color

import webbrowser as wb

def color_text_html(text, color="black"):
    # replace any newline with <BR> html code
    text = text.replace('\n', '<BR>')
    return "<FONT color=%s>%s</FONT>" % (color, text)


# this is your test text
text = """\
one
two
three
"""

# add some color html code
text_html = color_text_html(text, "red")

print(text_html)  # test

# write the text out as .htm file
fname = "simple_text.htm"
with open(fname, "w") as fout:
    fout.write(text_html)

# now display the text in your web browser
wb.open(fname)
1

This shows you how to use a helper function when sorting ...

'''sort_by_last_name1.py
sort names in format "first middle last" by the last name
'''

import pprint

def by_last_name(name):
    """
    helper function to sort by last name
    assume names are "first middle last"
    """
    return name.split()[-1]

# some sample names for testing
# format is first middle last
names = """\
Fred M. Ferkel
Carolus D. Arm
Carl S. Gustafson
Ben M. Over
Rosa X. Parker
Larry Marsh
Lola Q. Zumokar
Heinrich S. W. Buzen
"""

# convert to a list
name_list = [name for name in names.split('\n') if name]

print("names unsorted:")
pprint.pprint(name_list)

print('-'*35)

print("names sorted by last name:")
pprint.pprint(sorted(name_list, key=by_last_name))

'''result >>
names unsorted:
['Fred M. Ferkel',
 'Carolus D. Arm',
 'Carl S. Gustafson',
 'Ben M. Over',
 'Rosa X. Parker',
 'Larry Marsh',
 'Lola Q. Zumokar',
 'Heinrich S. W. Buzen']
-----------------------------------
names sorted by last name:
['Carolus D. Arm',
 'Heinrich S. W. Buzen',
 'Fred M. Ferkel',
 'Carl S. Gustafson',
 'Larry Marsh',
 'Ben M. Over',
 'Rosa X. Parker',
 'Lola Q. Zumokar']
'''
0

Windows in its infinite oddity has chosen to us the backslash '\' in its path names. However it will work with the normal slash '/' of the unix systems. in a string things like '\temp' will be interpreted as tab and 'emp'. So why not replace the '\' with '/'? Easier said than done as you will see in this example:

# experiments to convert
# r"a\b\c\d\e.aaa" to "a/b/c/d/e.aaa"

# make sure you make s a raw string
s = r"a\b\c\d\e.aaa"

# gives SyntaxError: EOL while scanning string literal
#s2 = s.replace('\', '/')
# gives SyntaxError: EOL while scanning string literal
#s2 = s.replace(r'\', '/')

# not the desired output
s2 = s.replace('\\', '/')
print(s2)  # a\b\c\d\e.aaa

# however this will work
s3 = "%r" % s
# test
print(s3)  # 'a\\b\\c\\d\\e.aaa'
# eval() converts repr back to str
s4 = eval(s3.replace(r'\\', '/'))
# success
print(s4)  # a/b/c/d/e.aaa

Edited by Lardmeister

1

Here is another way to do this:

# experiment to convert back slash to forward slash
# r"a\b\c\d\e.aaa" to "a/b/c/d/e.aaa"

def back2forw(c):
    '''helper function for list comprehension'''
    return (c, '/')[c == '\\']

# make sure you make s a raw string
s = r"a\b\c\d\e.aaa"

s2 = "".join([back2forw(c) for c in list(s)])  
print(s)
print(s2)

'''result >>
a\b\c\d\e.aaa
a/b/c/d/e.aaa
'''

The helper function uses True=1 and False=0

Edited by Lardmeister

Votes + Comments
thanks
1

This is the exploration of a toggle function using a list element as default argument:

'''toggle_function1.py
explore functions that toggle between 2 states every time they are called
'''

def toggle(x=[0]):
    '''
    toggles between True and False each time called
    '''
    x[0] = not x[0]
    return x[0]

# test
for k in range(6):
    print(toggle())

'''result >>
True
False
True
False
True
False
'''

Edited by Lardmeister

Votes + Comments
clever
1

Alternative way to do toggle function without global using attribute of function (which is also an object in Python).

def toggle():
    '''
    toggles between True and False each time called
    '''
    try:
        toggle.state = not toggle.state
    except AttributeError:
        toggle.state = True
    return toggle.state

# test
for k in range(6):
    print(toggle())
print('Toggle state is %s.' % toggle.state)

'''result >>
True
False
True
False
True
False
Toggle state is False.
'''

Even simpler is to use itertools module, now we keep state in variable in loop location:

from itertools import cycle

limit = 6
for counter, state in enumerate(cycle((True, False))):
    if counter >= limit:
        break
    print counter, state

print('Toggle state is %s.' % state)

"""Output:
0 True
1 False
2 True
3 False
4 True
5 False
Toggle state is True.
"""

Edited by pyTony

0

Here is a function to enter a list of numeric values:

# a function to input a list of numeric values

# this will work with Python2 and Python3
import sys

if sys.version_info[0] < 3:
  input = raw_input

def get_list(prompt):
    """
    loops until acceptable data or q (quit) is given
    returns a list of the entered data
    """
    data_list = []
    while True:
        sin = input(prompt)
        if sin == 'q':
            return data_list
        try:
            # check if number is integer or float data type
            if '.' not in sin:
                data = int(sin)
            else:
                data = float(sin)
            data_list.append(data)
        except ValueError:
            print("Enter numeric data!")

print('-'*20)  # 20 dashes

num_list = get_list("Enter a number (q to quit): ")

print(num_list)  # test
0

I prefer to send the quit condition as a second argument to the list entry function. That way, if you need 'q' as a valid list member, you can use something else to stop the loop (also works better for folks whose language does not use a 'q' word to mean "quit"). The second argument can be a string to match against, or it could be a function that takes a string and returns a boolean. The latter is the most general, but also more trouble than it is worth in many cases.

Edited by griswolf: clarify language issue

1

Could be the start of a word game:

# a simple rotate cipher

from collections import deque

def rotate_right(text, n=1):
    """
    use deque to rotate text n steps to the right
    return rotated text
    """
    rot_right = deque(text)
    rot_right.rotate(n)
    return "".join(rot_right)

def rotate_left(text, n=1):
    """
    use deque to rotate text n steps to the left
    return rotated text
    """
    rot_left = deque(text)
    rot_left.rotate(-n)
    return "".join(rot_left)

# cipher the text by rotating 3 steps
text = 'peanuts'
n = 3
print(rotate_right(text, n))  # utspean

# decipher the text
text = 'utspean'
print(rotate_left(text, n))  # peanuts
1

Temperature conversion from C to F or F to C is allways popular. Here is a way to make you scratch your head ...

'''Class_Temperature2.py
a class to convert F to C or C to F

tested with python32, python33
Python27 needs class Temperature(object)
'''

class Temperature():
    """
    allows you to convert F to C or C to F
    double underline prefix makes method private to class
    """
    def __init__(self):
        self.celsius = 0.0
    def __getFahrenheit(self):
        return 32 + (1.8 * self.celsius)
    def __setFahrenheit(self, f):
        self.celsius = (f - 32) / 1.8
    # property() combines get and set methods into one call
    # celsius and fahrenheit define each other
    # only one is needed to be given
    fahrenheit = property(__getFahrenheit, __setFahrenheit)


# create the class instance
t = Temperature()

# convert Celcius to Fahrenheit
t.celsius = 0
print("%0.1f C = %0.1f F" % (t.celsius, t.fahrenheit))

# convert Fahrenheit to Celsius
t.fahrenheit = 98
print("%0.1f F = %0.1f C" % (t.fahrenheit, t.celsius))

'''result ...
0.0 C = 32.0 F
98.0 F = 36.7 C
'''

Edited by vegaseat: exception for python27

0

Yes, it makes me to scratch mine. After running the code:

>>> t.fahrenheit = 10
>>> print("%0.1f F = %0.1f C" % (t.fahrenheit, t.celsius))
10.0 F = 37.0 C
>>> t.celsius=10
>>> print("%0.1f F = %0.1f C" % (t.fahrenheit, t.celsius))
10.0 F = 10.0 C
>>> 
0

Thanks Tony, seems to happen with Python27 only.
Python27 needs to inherit object:
class Temperature(object)
With Python3 object is default.

Edited by vegaseat

0

Python like java operates on object. At least python is not purely OB. but the concepts are similer.

1

A class that creates a persistent list can be used for some interesting applications ...

'''Class__persist1.py
find all integers in a series of texts
create a persistent list of all finds
tested with Python27, Python32 and Python33
'''

import re

class Persist_list_int():
    """
    class to make a list persistent
    """
    def __init__(self):
        # this list is persistent
        self.all_items = []

    def __call__(self, text):
        """
        allows class instance to be called with argument text
        """
        # just a simple test of the persistent list
        # regex to find all integers in a given text
        items = re.findall("\d+", text)
        self.all_items.extend(items)
        return self.all_items


# create class instance
find_int = Persist_list_int()

# call instance
print(find_int('12 days and 17 hours'))   # ['12', '17']
print(find_int('about 15 minutes ago'))   # ['12', '17', '15']
print(find_int('we are leaving at 6:45')) # ['12', '17', '15', '6', '45']
print(find_int('you owe me $123.48'))     # ['12', '17', '15', '6', '45', '123', '48']

Edited by vegaseat

1

Here another processing for the vegaseat text. No re, no classes. list of list of ints result instead of flat list of strings. Added my own test case to show missing of the recognition of negative numbers. Negative numbers could be catched by re with [+-]*\d+ as shown

from itertools import groupby
from operator import methodcaller
import re

def find_int(t):
    return  [int(''.join(n)) for is_digit, n in groupby(t, methodcaller('isdigit'))
             if is_digit]

tests = ('12 days and 17 hours',
        'about 15 minutes ago',
        'we are leaving at 6:45',
        'you owe me $123.48',
        'Temperature can go until -40 C in Finland')

print([re.findall('[+-]*\d+', t) for t in tests])

#negative value  is not catched as negative!
print([find_int(t) for t in tests])

"""Output
[['12', '17'], ['15'], ['6', '45'], ['123', '48'], ['-40']]
[[12, 17], [15], [6, 45], [123, 48], [40]]
"""

Edited by pyTony

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.