Python: Difference between revisions

From bibbleWiki
Jump to navigation Jump to search
Line 26: Line 26:
</syntaxhighlight>
</syntaxhighlight>


= Scalar Types, Operators and Control =
= Scalar Types, Operators, Control and Other =
== Types ==
== Types ==
* int (42)
* int (42)

Revision as of 05:50, 17 July 2020

Intro

Python 2 and 3 differences

print "fred" // OK Python 2
print("fred") // Not OK Python 2

Whitespace

Uses full colon and four spaces instead of brackets e.g.

for i in range(5):
    x = i * 10
    print(x)

Rules

  • Prefer four spaces
  • Never mix spaces and tabs
  • Be consistent on consecutive lines
  • Only deviate to improve readability

Help

help(object) gives help. e.g. for the module math

help(math)

Scalar Types, Operators, Control and Other

Types

  • int (42)
  • float (4.2)
  • NoneType (None)
  • bool ( True, False) 0 = False !=0 = True

Operators

  • == value equality
  • != value inequality
  • < less-than
  • > greater-than
  • <= less-than or equal
  • >= greater-than or equal

Control

if statementes

if True: 
    print("Its true")

h = 42
if h > 50: 
    print("Greater than 50")
elif h < 20:
    print("Less than 20")
else:
    print("Other")

while loops

while c != statement0: 
    print(c)
    c -= 1 // c = c-1
    print("Its true")

while True: 
    response = input()
    if int(response) % 7 == 0: 
       break

for loops

cities = ["London", "Paris", "Berlin"]

for city in cities:
  print(city)

Other

Conditional Expressions =

No big surprise but

# Condition statement
if condition:
    result = true_value
else: 
    result = false_value

# Condition expression (elvis result ? a:b
# result = true_value if condition else false_value
def sequence_class(immutable)
  return tuple if immutable else list

Data types

str

Double and single quotes are supported. Strings are immutable. Multiline

"""This is 
a multiline
string"""

m = "This string\nspans multiple\nlines"

Raw Strings like c# @

path = r'C:\users\merlin\Documents'

Format string

m = "The age of {0} is {1}".format('Jim', 32)
print(m) //  The age of Jim is 32

# Or without numbers
m = "The age of {} is {}".format('Jim', 32)


# f-strings are like c#
value = 3000
m = f"The value is {value}"

bytes

These work like strings, well ascii strings as and can be created like below

b'some bytpes'
print(b[0]) // 115

decoding to bytes

norsk = "some norsk characters"
data = norsk.encode('utf8')
norwegian = data.decode('utf8')

lists

General

List are a sequence of lists

m = [1,14,5]

// Can be different types
m = ['apple', 7, false]

// Add are mutable
b = []
b.append(1.666)
b.append(1.4444)
print(b) // [1.666, 1.4444]

// Constructor
print(list("characters")) // ['c','h','a','r','a','c','t','e','r','s']

Negative indexing

You can use negative indexing - errrr

s = [3,186,4431,74400, 1048443]
print(s[-1]) // 1048443
print(s[-2]) // 74400

Slicing

Subscript of lists can be achieved with the following

s = [3,186,4431,74400, 1048443]
print(s[1:3]) // 186, 4431
print(s[1:-1]) // 186, 4431, 74400

List Comprehension Syntax

Generally this is

[expr(item) for item in iterable]
words = "Why sometimes I have believed"
print([len(word) for word in words]) // [3,9, 1, 4, 8]

Dict

General

Dict are value pairs

m = {'1': 'Apple', '2': 'Orange'}

print(m['1']) // Apple

# Replaces
m['1'] = 'Banana']
print(m['1']) // Banana

# Update will add if it does not exist or replace
m.update(2:'Applie')

Dict Comprehensions

Like lists above

{expr(key:) expr(value) for item in iterable}
country_to_capital = { 'UK': 'London',
                       'Brazil': 'Brasilia',
                       'Sweden': 'Stockholm' }

capital_to_country = { capital: country for country, capital in country_to_capital.items()}
print(capital_to_country) // {'Brasilia': Brazil, 'London': 'UK', 'Stockholm': 'Sweden'}

Set

Set are values like a dictionary with no key and must be unique

k = {91,109}
k.add(54)

# Error if not found
k.remove(91) 

# No Error if not found
k.discard(91)

With sets we can compare. e.g.

blue_eyes = {'Olivia','Harry', 'Lily', 'Jack','Amelia'}
blond_hair = {'Harry', 'Jack','Amelia', 'Mia','Joshua'}

# Combined
print(blue_eyes.union(blond_hair)) // {'harry','Jack','Amelia','Joshua','Mia','Olivia','Lily'}

# In both
print(blue_eyes.intersection(blond_hair)) // {'harry','Jack','Amelia'}

# Not in this
print(blond_hair.difference(blue_eyes)) // {'Mia','Joshua'}

# Not in other
print(blond_hair.symmetric_difference(blue_eyes)) // {'Mia','Joshua','Olivia','Lily'}

Tuples

Tuples look like lists but have round brackets.

t = ('Apple', 3.5, False)
# to make a single you need to use the trailing comma or it thinks it is a single type e.g.
t = ('Apple',) 
# to index one with pairs use second index e.g
t = ((220,284),(220,285),(220,284),(220,281))
print(t[0][1])

Unpacking like javascript works and swapping

def minmax(items):
    return min(items), max(items)

lower, upper = minmax([83, 33, 84,32, 85, 31, 86])
print(lower) // 31
print(upper) // 86

a = 'Apple'
b = 'Pear'

a, b = b, a

print(a) // Pear
print(b) // Apple

Ranges

Range supports arguments stop, start, stop or start, stop, step. e.g.

# 0-5
range(5) 

# 10-20
range(10,20)

# 10-20 step 2
range(10,20,2)

Iteration

Iterators

Here is how to iterate

s = [1,2,3,4]
myIterator = iter(s)
item1 = next(myIterator)
print(item1) // 1
item2 = next(myIterator)
print(item2) // 2

Generators

Generator functions

This is just like javascript redux stuff

def gen123():
    yield 1
    yield 5
    yield 3

myIterator = gen123()
print(next(myIterator)) // 1
print(next(myIterator)) // 5
print(next(myIterator)) // 3
print(next(myIterator)) // Exception

# Or 
for v in gen123():
    print(v)
...
1
5
3

Generator Expressions

Syntax can be defined as

(expr(item) for item : iterable)
million_squares = (x*x for x in range(1,1000001))

# Generate and output last 10
list(million_squares)[-10:]

# Again will yield nothing
list(million_squares)

Iteration tools

islice

from itertools import count, islice

thousand_primes = islice( (x for x in count() if is_prime(x), 1000)
# thousand_primes is a special islice object which is iterable
# converting to a list
list(thousand_primes)[-10:]
[7841,7853, ..... 7919]
# so to sum first thousand primes
sum(islice( (x for x in count() if is_prime(x), 1000))
3682913

zip

Combine groups together e.g.

sunday = [10,20,30]
monday = [101,201,301]
for item in zip(sunday, monday)
    print(item)
...
(10,101)
(20,201)
(30,301)

Exceptions

General

def convert(s):
    try:
      number = ''
      for token in s:
         number += DIGIT_MAP[token]
      x = int(number)
    # Can be on one line
    # except (KeyError, TypeError):
    except TypeError:
       x = -2
       raise # rethrow
    except KeyError:
       x = -1
       raise # rethrow
    return x

Modularity

Functions

General

These are created as below

def foo(arg1, arg2):
    return arg1 * arg2

Defaults

def foo(arg1, arg2=9):
    return arg1 * arg2

Be aware that the def assignment is only run once. Therefore These are created as below

def add_spam(menu=[]):
    menu.append('spam')

add_spam() // ['spam']
add_spam() // ['spam','spam']

Advice is to make default arguments not mutable. i.e. not strings and not ints

def add_spam(menu=None):
    if(menu==None)
       menu = []
    menu.append('spam')
    return menu

add_spam() // ['spam']
add_spam() // ['spam']

Importing defs

Best to be selective

from words import (fetch_words, print_words)

// could be BAD BAD!!
from words import *

Passing arguments

import sys

if __name__ == '__main__':
    main(sys.argv[1])

Comments

def fetch_words(url):
    """Fetch a list of words from a URL.
    
    Args:
        url: The URL of UTF-8 text document.

    Return:
        A list of strings containing the words from
         the document.
    """
    story = urlopen(url)
    story_words = []
    for line in story:
        line_words = line.decode('utf8').split()
        for word in line_words:
            story_words.append(word)
    story.close()
    return story_words

Scope of Objects

Types of Scope

  • Local - Inside current function
  • Enclosing - Inside enclosing function
  • Global - At the top level of the module
  • Built-in - In the special builtins module

Overriding Scope

Not using global creates a new count and it shadows the global count.

count = 0

def show_count(): 
    print(count)

def set_count(c)
    global count = c

set_count(5)
show_count()

Objects and Types

Named references to objects

Assigning variables is the same as references. Use id() to prove this.

s = [1,2,3]
r = s
s[0] = 500
print(r)
[500,2,3]
p = [4,5,6]
q = [4,5,6]
print(p == q) // True
print(p is q) // False

Passing Arguments are like references

Passing arguments is like passing references

m = [9,15,24]
def modify(k):
    k.append(39)
    print("k = ", k)

modify(m)
k = [9,15,24, 39]
print(m)
[9,15,24, 39]

Passing Arguments are like references II

Or are they. g is reassigned not mutated

f = [14, 23, 37]
def replace(g):
    g = [17,28, 45]
    print("g = ", g)

replace(f)
g = [17,28, 45]
print(f)
[14,23,37]

Classes

General

class Fight:
    def __init__(self, registration, model, num_rows)
       self._registration = registration
       self._model = model
       self._num_rows = num_rows

   def registration(self):
       return self._registration

   def model(self):
       return self._model

   def num_rows(self):
       return self._num_rows

Access

There is no public, protected or private in Python

Inheritance

This is achieved using brackets on the name

class MyBaseClass:
   def registration(self):
       return self._registration

   def model(self):
       return self._model

   def num_rows(self):
       return self._num_rows

class Fight(MyBaseClass):
    def __init__(self, registration, model, num_rows)
       self._registration = registration
       self._model = model
       self._num_rows = num_rows

__call__

No idea why this is good but essentially it allows to call an instance of an object with no method or rather the method name __call__

class Test
    def __init__(self)
       self._cache = {}

    def __call__(self, arg1)
       if arg1 not in self._cache:
          self._cache[arg1] = socket.gethostbyname(arg1)
          return self_cache[host]

f = Test()
f('bibble.co.nz')

File IO

The with is used like using in c#

Reading

with open('dog_breeds.txt', 'r') as reader:
    # Read and print the entire file line by line
    line = reader.readline()
    while line != '':  # The EOF char is an empty string
        print(line, end='')
        line = reader.readline()

Packages

Packages

Python finds packages by looking at sys.path. You can see this by doing

import sys
sys.path 

# For entry 0
sys.path[0]

# To add you can
sys.path.append('/mypath');

Another approach is to add your path to PYTHONPATH

export PYTHONPATH=$PYTHONPATH:/mypath

Make a Package

mkdir -p /mypath/reader
touch /mypath/reader/__init__.py

For a simple reader class the contents of __init__.py may be (absolute)

from reader.reader import Reader

For a simple reader class the contents of __init__.py may be (relative)

from .reader import Reader

Controlling whats imported

You can do this by specifying the __all__ content. Looks like a def file in windows dlls. e.g.

from reader.compressed.bzipped import opener as bz2_opener
from reader.compressed.gzipped import opener as gzip_opener

__all__ = ['bz2_opener', 'gzip_opener']

Namespace packages

These are packages split across to directories and the root directories do not contain a __init__.py. Importing namespace packages

  • Python scans all entries in sys.path
  • if a matching directory with __init__.py is found, a normal package is loaded
  • if foo.py is found then it is loaded
  • Otherwise, all matching directories in sys.path are considered part of a namespace package
 path1
   | 
   --split_farm
     | 
     -- bovine
       | 
       -- __init__.py
       -- common.py
       -- cow.py
       -- ox.py

 path2
   | 
   --split_farm
     | 
     -- bird
       | 
       -- __init__.py
       -- chicken.py
       -- turkey.py

Executable Directory

You can make a executable by providing a __main__.py in the directory.

  project
  |
  -- __main__.py
  -- project
       | 
       -- __init__.py
       -- stuff.py
  -- setup.py

You can then run the code with

python3 reader

Zipping up the directory and it can be distributed as python treats zips a directories. e.g.

python3 reader.zip