In [1]:
import this


The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

print "hello astronomy"


In [10]:
# set the midpoint
midpoint = 25

# make two empty lists
lower = []; upper = []

# split the numbers into lower and upper
for i in range(50):
    if (i < midpoint):
        lower.append(i)
        # print("i lower = ",i)
    else:
        upper.append(i)
        # print("i upper = ",i)
        
print "lower:", lower
print "upper:", upper


lower: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
upper: [25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]

Note: Most widely used style guide in Python is known as PEP8, and can be found at https://www.python.org/dev/peps/pep-0008/.

Python is dynamically-typed: variable names can point to objects of any type:


In [14]:
x = 1         # x is an integer
x = 'hello'   # now x is a string
x = [1, 2, 3] # now x is a list

# All python variables are pointers, so if we have two variable pointing to same mutable object, then changing
# one will change other as well.

x = [1, 2, 3]
y = x

# both x and y are pointing to same object
print y

x.append(4) # append 4 to the list pointed to by x
print y # y's list is modified as well!


[1, 2, 3]
[1, 2, 3, 4]

This behavior might seem confusing if you're wrongly thinking of variables as buckets that contain data. But if you're correctly thinking of variables as pointers to objects, then this behavior makes sense.

Note also that if we use "=" to assign another value to x, this will not affect the value of y – assignment is simply a change of what object the variable points to:


In [15]:
x = 'something else'
print(y)  # y is unchanged because now x is pointing to other object, but the previously pointed object is not changed


[1, 2, 3, 4]

In [17]:
#Everything is Object

x = 'A string'
type(x)


Out[17]:
str

In [18]:
x = 89
type(x)


Out[18]:
int

In [19]:
x = 89.25
type(x)


Out[19]:
float

In [26]:
#converting decimal to binary
print "binary 10:", bin(10)

# OR operation
print "4 OR 10:  ", bin(4 | 10)


binary 10: 0b1010
4 OR 10:   0b1110

In [27]:
-1 == ~0


Out[27]:
True

In [28]:
1 in [1, 2, 3]


Out[28]:
True

In [29]:
2 not in [1, 2, 3]


Out[29]:
False

Python integers are variable-precision, so you can do computations that would overflow in other languages:


In [32]:
2 ** 200


Out[32]:
1606938044258990275541962092341162602522202993782792835301376L

In [52]:
for i in range(2):
    print(i)


0
1

In [53]:
i = 0
while i < 2:
    print(i)
    i += 1


0
1

In [ ]:


In [35]:
def _fibonacci(N,a=0,b=1):
    try:
        if N < 0:
            raise ValueError #if not raised, this program will not raise any error,insted blank vector will be returned
        L = []
        # a, b = 0, 1 #getting a and b as default arguments
        while len(L) < N:
            a, b = b, a + b
            L.append(a)
        return L
    except ValueError:
        print "ValueError : N must be non-negative"

In [36]:
_fibonacci(10)


Out[36]:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

In [37]:
_fibonacci(-10)


ValueError : N must be non-negative

In [50]:
def catch_all(*args, **kwargs):
    print("args =", args)
    print("kwargs = ", kwargs)

In [51]:
catch_all(1, 2, 3, a=4, b=5)


('args =', (1, 2, 3))
('kwargs = ', {'a': 4, 'b': 5})

In [58]:
data = [{'first':'Guido', 'last':'Van Rossum', 'YOB':1956},
        {'first':'Grace', 'last':'Hopper',     'YOB':1906},
        {'first':'Alan',  'last':'Turing',     'YOB':1912}]

In [60]:
# sort alphabetically by first name
sorted(data, key=lambda item: item['first'])


Out[60]:
[{'YOB': 1912, 'first': 'Alan', 'last': 'Turing'},
 {'YOB': 1906, 'first': 'Grace', 'last': 'Hopper'},
 {'YOB': 1956, 'first': 'Guido', 'last': 'Van Rossum'}]

In [8]:
def safe_divide(a, b):
    try: #try
        return a / b
    except ZeroDivisionError: # catch
        print "ZeroDivisionError occoured and caught"
        return 1E100
    except TypeError:
        print "TypeError occoured and caught"

In [6]:
safe_divide(1, 2) #no error


Out[6]:
0

In [9]:
safe_divide(2, 0) #ZeroDivisionError


ZeroDivisionError occoured and caught
Out[9]:
1e+100

In [10]:
safe_divide(2,'str') #TypeError


TypeError occoured and caught