Wednesday, April 20, 2016

Python over C# / Java

Most people say the python is elegnet over Java. They are correct :)

Let's go over the basics, and I believe you will agree in the end...


Syntax


Curly brackets for scopes are gone.  we use the indentation instead.
if (x>10) :
  print("somewhat big")
  if x>50 :
     print "big"

Strings can be anything between 'x'  or "x"  or """x""" , in the later case new line in the editor is translated to new line (\n) in the string, so what you see is what you get.


and, or and not  are the actual operators(!) not &&,||,!.
"in" replaces the contains operator: if  'a' in ('a','b','c')
[not so great?]  instead of max=(a>b)?a:b  ,  use max = a if (a>b) else b
very easy way to wrap a function with a decorator on function like @args-check




loops

while and for loops have an optional "else" clause which will be triggered only when the loop exists normally on the condition failure (and not in "break").  This is very useful and save ugly code in end of java loops where you are unsure what caused you to pass the loop.

for loops are always using "in"
for odd in range(1,10,2) : print odd  #   from 1 , as long as <10 ,jump of 2
for item in list : print item
for key in dictionary: print key
for value in dic.itervalues() : print value

built in data structures

no arrays!  python asks us to use a higher level structure, like list.
list = []  is like Java ArrayList of Objectstuple=()  is immutalbe ArrayList of Objects

some syntactic sugar for all sequences data structures (list,tuple and string too!):

list[0]
list[0,3] returns a slice with elements 0,1,2
list += [ "hello" , "world"]   #adds all elements of the second list
if  "hello" in list : print "world"

dict = { "key1" : "value1" , "key2" : value2 }
len(dict)  # return 2
dict.update( { "key1": "updated1" , "key100":"value100"}) #update by another dict
if "key100" in dict:  print ("this was expected")
dict["key100"] = "updated100"
del(dict["key100"])  #both key and value are deleted
dict.items = list of key,value tuples   [ ("key1","value1", "key2,value2")]
dict(dict.items)  # transform a list with tuples into a dictionary

set is similiar to hashset
mySet = { "key1" , "key2" , "key3")
mySet = set(["key1","key2","key3" )


Better than the ugly :  if (list!=null && list.length>0)

if  list :   #nil=false and empty list = false too
  #do something with the list
else
  print("empty list or nil list, do exception path!")


Super cool documentation and unit-testing feature

the first declaration inside a method can be a string, with code examples.
def add(x,y)
  """ adds x to y and return the sum
  >>> add(1,1)
  2
 >>> add(-1,101)
 100
"""
  return x+y

the documentation is accessed using add.__doc__
doctest can run all the code samples in the documentation.

import doctest
if __name__ == "__main__" ;  #optional "if" ,means run this code only if you don't import this
  doctest.testmod()
it will search for all the mehod documentation, and run each example.  if there is a problem, it will output the expected and the actual value.


printing


simple, in this case we indent to the left the name, for column size of 20, then price as float.
print("Name={name:<20s} Price:{price:8.2f}. format(a="golden-crown", b=2000.01) )
print("Name={name:<20s} Price:{price:8.2f}. format("golden-crown", 2000.01) )  #same


in many case, you have a varialbes instead, you can do this trick and use the general method locals() which pass the dictionary of current scope values:
print("Name={name:<20s} Price:{price:8.2f}. format(**locals() ))
As a sidenote: You can use the same trick with your own dictionary.
  def foo(a,b,c,d) :  print (a,b,c,d) #method with four arguments
  myDic = { "c":0.4 , d:"description" , "a": 55 , "b": true , }  #dictionay somewhere in the code
  foo(**myDic)  #will pass the right values from the dictionary to the right arguments
  myList = [ 55, true, 0.4 , "description"]
  foo(*myList) #does the same, but here order is important

print itlsef is quite strong
print( a,b, sep="\n")  will seperate with newline, default is one space.
fh = open ("data.txt", "w")
print("lets write to file. why should it be difficult or different then regular print?", file=fh)
fh.close()



exceptions (see the else part)

try:
   f = open("file.txt")
except IOError as (errnum, errstr):
  print("IO exception number {0} : {1}".format(errnum,errstr)
except (ValueError, InventedError)
  print("other known error happened")
except:  #other unknown error
   print("unknown error, for this, we propogate up", sys.exc_info()[0]))
   raise
else:
    #read the file
    print( f.readlines())
    f.close()

finally:
   print("just like in java, very optional"

assert is a synatactic sugar to if  not <condition>: raise AssertionError("msg")
assert  x>0 , "x must be above zero, it wasn't! fix this for assertion to pass"




No comments: