# Simple And Clever Python Functions

There are quite a lot of simple snippets built in basic packages or by stackoverflow experts. It provides a great deal of inspiration to hands-on work.

1. second largest value searching. Introducing two values m1, and m2 to let the two recycle through and always return the less value. And then a simple modification of initial values m1, m2, can yield the second smallest value instead.

def second_largest(numbers):
m1, m2 = None, None
for x in numbers:
if x >= m1:
m1, m2 = x, m1
elif x > m2:
m2 = x
return m2
print second_smallest([1, 2, 3, 4])
2
#to find the second smallest
def second_smallest(numbers):
m1, m2 = float(‘inf’), float(‘inf’)
for x in numbers:
if x <= m1:
m1, m2 = x, m1
elif x < m2:
m2 = x
return m2

Other ways such as sort to skin the cat

def second_smallest(nubmers):
nubmers = sorted(nubmers)
count = 0
l = []
for i in nubmers:
if(i not in l):
l.append(i)
count+=1
if(count==2):
break

return max(l)

Or to use index value to pinpoint the second smallest values. However, the below snippet is not water-proof, think about the possibility of duplicated value in a list, the method of ls[ls.index(value)] could lead to multiple positions. Nevertheless, it’s also a good angle to conquer the problem.

def second_min_index(ls):
min_value = min(ls)
max_value = max(ls)

# The smallest number changes into the largest.
for value in ls:
if value == min_value:
ls[ls.index(value)] = max_value

return ls.index(min(ls))

2. How to apply a function across the columns rather than rows?  A straightforward way is

def my_test(a, b):
return a % b
df[‘Value’] = df.apply(lambda row: my_test(row[a], row[c]), axis=1) #note this will throw error message “global name ‘a’ is not defined”, u’occurred at index 0″ because a or c columns should be quoted
df[‘Value’] = df.apply(lambda row: my_test(row[‘a’], row[‘c’]), axis=1)

What if the columns varies, how to apply the wildcard sort of computation?
Generally,

#**kwargs allows you to pass keyworded variable length of arguments to a function. You should use **kwargs if you want to handle named arguments in a function. Here is an example
def greet_me(**kwargs):
if kwargs is not None:
for key, value in kwargs.iteritems():
print “%s == %s” %(key,value)

>>> greet_me(name=”yasoob”)
name == yasoob
>>>greet_me(name = [1, 2, 3])
name = [1, 2, 3]

#Using *args and **kwargs to call a function
def test_args_kwargs(arg1, arg2, arg3):
print “arg1:”, arg1
print “arg2:”, arg2
print “arg3:”, arg3

# first with *args
>>> args = (“two”, 3,5)
>>> test_args_kwargs(*args)
arg1: two
arg2: 3
arg3: 5

# now with **kwargs:
>>> kwargs = {“arg3”: 3, “arg2”: “two”,”arg1″:5}
>>> test_args_kwargs(**kwargs)
arg1: 5
arg2: two
arg3: 3

#cover *args and **kwargs.
blog_1 = ‘I am so awesome’
blog_2 = ‘Cars are cool.’
blog_3 = ‘Aww look at my cat.’

def blog_posts(*args):
for post in args:
print(post)

blog_posts(blog_1,blog_2,blog_3)

# *args are like a list, **kwargs are like a dictionary.
def blog_posts_3(**kwargs):
for title, post in kwargs.items():
print(title,post)

blog_posts_3(blog_1 = ‘I am so awesome’,
blog_2 = ‘Cars are cool.’,
blog_3 = ‘Aww look at my cat.’)

import schedule
import time

def job():
print(“I’m working…”)

schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at(“10:30”).do(job)

while 1:
schedule.run_pending()
time.sleep(1)

from datetime import datetime

x=datetime.today()
y=x.replace(day=x.day+1, hour=1, minute=0, second=0, microsecond=0)
delta_t=y-x

secs=delta_t.seconds+1

def hello_world():
print “hello world”
#…

t = Timer(secs, hello_world)
t.start()

from datetime import date
from apscheduler.scheduler import Scheduler

# Start the scheduler
sched = Scheduler()
sched.start()

# Define the function that is to be executed
def my_job(text):
print text

# The job will be executed on November 6th, 2009
exec_date = date(2009, 11, 6)

# Store the job in a variable in case we want to cancel it