#Study Guide Python Study Guide
Use of private heap containing all Python objects and data structures. User has no control, done by interpreter.
Raw memory allocator: Ensure enough memory from OS
Most work done by object-specific allocators. Objects are all treated differently, due to each needing storage requirements and space/speed tradeoffs
Heap space is allocated by Python/C API
Python object have reference count, count of objects pointing to it. when reference count is zero object is freed. Make use of reference cycles to find all objects that are unreachable. Unreachable objects include container objects: lists, dicts, instances, classes, tuples. Ints / Strings are not containers. Knows about each of these and c
Used for pretty much everything, ordered, any type of object
list = [1, 2, 3]
list.insert(x)
#CAN ONLY USE .sort() ON LISTS
list.sort()
In Python, is small wrapper for C array (typically not used)
Represent basic values, chars, ints, floats, unicode. Corresponding varients for signed / unsigned
from array import array
x = array('l', [1,2,6,8])
x.append(4)
>>> array('l', [1, 2, 6, 8, 4])
Values separated by a comma, values inside are immutable
tuple = ‘hello’, 123, ‘world’
Unordered with no duplicates
set = {‘apple’, ‘orange’, ‘apple’, ‘pear’}
print(set)
>>> {‘apple’, ‘orange’, ‘pear’}
Can do relational algebra set operations on
a = set(‘abracadabra’)
b = set(‘alacazm’)
a - b
>>> {‘r’, ‘d’, ‘b’} etc etc
Dictionaries in Python are key: value pairs, unordered, implemented by a hashtable but used like hashmap
tel = {‘jack’: 4098, ‘sape’: 4139}
tel[‘guido’] = 4127
>>> {‘sape’: 4139, ‘guido’:4127, ‘jack’: 4098}
# or use constructor
dict( [ (’sape’, 4139), (‘guido’, 4127), (‘jack’, 4098) ] )
List uses .sort() to sort data for that instance
All other iterable data structures use sorted(), which returns a new sorted instance
Sort and sorted call timsort at C level, average complexity of O(n log n)
class Dog():
kind = 'canine' # class variable shared by all instances
# init must take argument if given
def __init__(self, name):
self.name = name # instance variable unique to each instance
self.tricks = []
def tricks(self):
self.tricks.append('sit')
class BigDog(Dog):
def tricks(self):
self.tricks.append('eat turkey')
d = Dog('Fido')
e = Dog('Buddy')
d.kind
>>> 'canine'
e.name
>>> 'Buddy'
The MRO algorithm handles how a class will inherit its attributes.
class First(object):
def __init__(self):
super(First, self).__init__()
print("first")
class Second(object):
def __init__(self):
super(Second, self).__init__()
print("second")
class Third(First, Second):
def __init__(self):
super(Third, self).__init__()
print("that's it")
x = Third()
>>>second
>>>first
>>>that's it
Resolves inits as: init is calculated below as:
Third --> First --> object --> Second --> object
Duplicates are removed
Third --> First --> Second --> object
Methods are then called from object back up
A more complicated example showing inheritance that crosses paths is defined as:
class First(object):
def __init__(self):
super(First, self).__init__()
print("first")
class Second(First):
def __init__(self):
super(Second, self).__init__()
print("second")
class Third(First):
def __init__(self):
super(Third, self).__init__()
print("third")
class Forth(Second, Third):
def __init__(self):
super(Forth, self).__init__()
print("that's it")
x = Forth()
>>>first
>>>third
>>>second
>>>that's it
Resolves inits as: init is calculated below as:
Forth --> Second --> First --> object --> Third --> First --> object
Duplicates are removed
Forth --> Second --> Third --> First --> object
Methods are then called from left to right, super to newest child
This is used for passing arbitray number of arguments to a function. In strict type coding languages this is typically seen as overloading, where multiple function definitions have the same name but variable arguments.
class DisplayOverloading
{
public void disp(char c)
{
System.out.println(c);
}
public void disp(char c, int num)
{
System.out.println(c + " "+num);
}
}
class Sample
{
public static void main(String args[])
{
DisplayOverloading obj = new DisplayOverloading();
obj.disp('a');
obj.disp('a',10);
}
}
However in Python this is atypical to use, and instead use variable amount of arguments via *args or **kwargs.
*: pass arbitrary number of arguments
**: pass arbitrary number of dict values
def func(*args)
. . .
def func(*args, **kwargs)
. . .
# — or --
def func(x, y, z)
. . .
list = [1,2,3]
function(*list)
dict = [‘x’:1, ‘y’:2, ‘z’:3]
function(**dict)
Set of symbolic names (members) bound to unqiue, constant values.
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
A class that contains abstract methods, methods that are declared but contain no implementations. Use as structures for what methods a subclass should contain. While typically not implemented in Python, useage of standard inheritance is prefered, they can be using the Python abc modul (Abstract Base Classes: https://docs.python.org/3/library/abc.html)
from abc import ABCMeta, abstractmethod
class Abstract(metaclass=ABCMeta):
@abstractmethod
def foo(self):
raise NotImplementedError('users must define foo to use this base class')
class Concret(Abstract):
def foo(self):
print('cat')
con = Concret()
con.foo()
>>> 'cat'
Where tests are added prior to creation of new feature. The new test contains expected behavior of the feature to be added and should not pass until implementation of feature is correct. Ensures developers are not writingt tests bases on output of development and ensures test cases are already written, speeding up development time / addition of features later.
White Box: tester knows implementation
Black Box: tester does not know implementation
For Python use the unittest model:
# Basic Example
import unittest
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def test_default_widget_size(self):
self.assertEqual(self.widget.size(), (50,50), 'incorrect default size')
def tearDown(self):
self.widget.dispose()
What are decorators?
Multithreading in Python Problems, deadlock, mutli read issues, etc.
Are they pass by reference?
Start at root (or search node) and explore each neighbor before going on to any of their children.
Start at root (or search node) and explore each branch completely before moving to the next branch
Data life cycle that includes the data's origins and where it moves over time. Helps tracing errors back to their sources. Allows for replaying specific portions for step debugging.
Centralized repository of information about data such as meaning, relationships to other data, origin, usage, and format. Storage of metadata. Can be seen with Entity Relationship Diagrams.
Typically read only table that provides information about the database.
- Includes all schema objects
- Space allocated and used by each schema
- Default values for columns
- Integrity constraint information
- Users and Priviledges and roles each user has
- Auditing info, who has access/updated schema objects
- In using relational databases, which type of databases are used: IBM DB2, PostgreSQL, Oracle?
- When doing test driven development, do the team use the Python standard libraries implementation of unit test? Or a third party library such as Nose?
- Do developers on this team use Windows or Unix based systems?
- Do developers on this team typically use an IED such as PyCharm or work in the terminal with text editors when developing?
- Which source management tools does the team typically use? Github, BitBucket, GitLab?