Python: Difference between revisions
Line 559: | Line 559: | ||
self._model = model | self._model = model | ||
self._num_rows = num_rows | self._num_rows = num_rows | ||
</syntaxhighlight> | |||
== __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__ | |||
<syntaxhighlight lang="python"> | |||
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') | |||
</syntaxhighlight> | </syntaxhighlight> | ||
Revision as of 05:40, 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 and Control
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 != 0:
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)
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