Python 3: Object Orientated Programming

  1. Object-orientated Design
    • design doesn’t only occur at the beginning, usually analysis, programming, design tend to overlap
    • objects are models of things that can do things and have certain things done to them
    • formally, an object is a collection of data and associated behaviors
    • OO Analysis:
      • looking at a problem, system or task and indentifying the objects and their interactions
      • Output is set of requirements
    • OO Design:
      • convert requirements into implementation specifications
      • name objects, define behaviors, and specify what objects can activate specific behaviors on other objects
      • focus on how things should be done
      • output is implementation specification e.g. a set of classes and interfaces that could be implemented in any object-orientated language
    • OO Programming:
      • process of converting design into a working program
    • In modern world, most development happens in an iterative development model
    • classes describe objects and distinguish between different types of objects
    • UML (Unified Modeling Language) diagrams describes relationships or associations between classes
    • Data is represented as properties or attributes
    • Actions are called methods and can take parameters or access data of an object
    • Hiding details and creating the public Interface
      • key purpose of modeling an object is to determine what the public interface will be
      • attributes and methods that other objects can use to interact with that object
      • hiding implementation or functional details is called information hiding 
      • sometimes interchanged with encapsulation, but in encapsulation not necessarily hidden
      • designing public interface very important because difficult to change later, because will break client objects calling it
      • abstraction: dealing with the level of detail that is most appropriate to a given task
      • abstraction is the process of encapsulating information with separate public and private interfaces
    • Composition
      • composition is the act of collecting together several objects to compose new ones
      • composition is good when objects are part of other objects, but in computer programming usually describing abstract ideas
      • object diagram describes system at a specific state in time and interaction between objects
      • if outside object controls when related object is created or destroyed composition is more suitable
      • if related object is created independently and can outlast outside object an aggregate relationship makes more sense
    • Inheritance
      • The is a relationship is formed by inheritance
      • Inheritance is like a family tree, classes can inherit attributes and methods from another class
      • e.g. individual chess pieces can inherit from a generic Piece class and override moves
      • abstract classes can declare abstract methods that indicates a method, but doesn’t specify an implementation
    • Polymorphism
      • Polymorphism is ability to treat a class differently based on the subclass
      • Python uses duck-typing: ignores an object’s type and determine suitability based on presence of certain properties and methods
      • e.g. a board implemented in Python could take any object that has a move method and use it
    • Multiple Inheritance
      • subclasses can inherit functionality from multiple parent classes
      • useful if creating object with two distinct set of behaviors
      • usually want to avoid if overlapping interface
      • Inheritance is good when there is a clear is a relationship, programmers often use when objects only distantly related
  2. Objects in Python
    • PEP8 recommends classes named using CamelCase convention
    • Can assign arbitrary values to objects with dot notation
    • Docstrings
      • when doing OOP, important to write API documentation that clearly summarizes what each object and method does
      • Python supports this with docstrings
      • docstrings should clearly summarize purpose of class or method and explain parameters whose usage is not immediately obvious
      • also good place to include short examples
      • first line following the definition and should be indented like the following code can have (‘,”,  or ”’)
      • help([class or function name]) will show docstrings
    • Modules
      • for small programs, can have classes in one file
      • for larger ones, use modules (just python files)
      • don’t use ‘from database import *’
      • it makes it hard to know where something may be coming from and you will forget as time passes, maintenance becomes a nightmare
      • can also import many unnecessary objects, modules or classes
      • no variables should come from thin air
    • Packages
      • package: collection of modules in a folder. place a empty file named init.py
      • absolute imports: specify complete path
      • from ecommerce.products improt Product; product = Product()
      • from ecommerce import products; produt = products.Product()
      • relative imports: find a class, function or module relative to current module
      • one period, for files next to each other, two periods to check in parent file
      • best to always put code into functions otherwise will execute upon import
      • can also put classes into functions/methods, but usually better for one-off items
    • Access to Data
      • Python doesn’t have access control
      • can prefix internal methods with an underscore (understood by python programmers)
      • most python programmers won’t touch name-mangled variables (one or two underscores) unless compelling reason to do so
      • can import more directly if included in init.py file
  3. When Objects are Alike
    • inheritance is one way to avoid duplicate code
    • all python classes are subclasses of ‘object’
    • a subclass is derived from a parent or extends the parent
    • class variables are shared among all instances
    • you can also add functionality to existing built-in classes (i.e. list, dict, set, file, str)
    • overriding is altering or replacing a method of the superclass with a new method
    • super lets you call parent class directly
    • Multiple inheritance
      • as a rule of thumb, if you think you need multiple inheritance you probably don’t, if you know you need it, you probably do
      • most useful form of multiple inheritance is called a mixin
      • mixins meant to be inherited to provide extra functionality
      • diamond inheritance where two subclasses override a method and get extended by another subclass, may result in multiple calls to same thing
      • generally makes code messy and hard to follow
    • Polymorphism
      • same method name can have multiple implementations per subclass
      • because of duck typing, can use any object that provide required behavior without forcing ti to be a subclass
      • because any object can provide the correct interface, the need for polymorphic common superclasses reduced in Python
  4. Expecting the Unexpected
    • exceptions are special error objects that are derived from BaseException
    • handle exceptions by wrapping in a try…except clause
    • might be good to specify the type of exception you are trying to catch (i.e. ZeroDivisionError, NameError, etc)
    • can catch specific errors and general errors
    • can use try…except…else(if no exceptions)…finally(always runs)
    • Most exceptions inherit from Exception class which is a subclass of BsaeException
    • SystemExit and KeyboardInterrupt derive directly from BaseException
    • except will catch everything including the two above, usually want to catch Exception which excludes them
    • can define own exceptions as classes that inherit ‘Exception’
    • can handle the information regarding the error object
    • better to use exceptions than handle directly with if more flexible and less messy (what do you return? how will you check for it?)
    • exception help you design the flow of your program and should not be avoided
    • exceptions are good communication tools
    • use exceptions to handle failure, not return values
  5. When to Use Object-orientated Programming
    • When to use?
      • no reason to add an extra level of abstraction if it doesn’t help organize code
      • OO code is relatively self documenting
      • generally the more complicated a set of data is, more likely it is to have functions specific to that data
      • focus on how it will be used? once? multiple times? for different types of things?
      • focus on interaction between objects and inheritance relationships
    • Properties to add behavior to class data
      • some languages like Java recommend getters and setters
      • in python can use property object to check if valid
      • can take a getter, setter, delete and docstring
      • usually only defined with the first two parameters
      • e.g. under class [example]: name=property(_get_name, _set_name)
    • Using Decorators with property
      • modify functions dynamically by passing in a function and returning a new function
      • can use property function to turn a get function into a property
      • methods should represent actions
      • diff between attribute and property is we can invoke custom actions when a property is retrieved, set, or deleted
      • e.g. when lookup is expensive or want to cache
      • good for things that need to be calculated on the fly
    • Managing Objects
      • high-level objects that manage other objects tend to represent concrete ideas
      • breaking out steps for readability, extensiblity (can modify easier), and partitioning (another class may want to use only certain parts)
    • Remove Duplicate code (DRY)
      • boils down to readability and maintainability
      • code should always be written to be readable first
      • Inheritance is one way to reuse code
      • Can also pass an object with object with appropriate method
      • any inheritance relationship can be modeled as a composition relationship, but not the other way around
  6. Python Data Structures
    • initialized objects from the object class can’t be assigned values to save space
    • tuples are in order and immutable
      • generally should have values that are different type from each other
      • generally used to aggregated different pieces of data
      • suffers from readability though
      • named tuples are good for grouping read-only data / object w/ no behavior
    • Dictionaries great where the keys represent different instances of similar objects
      • also good where each key represents some aspect of a single object
      • dictionaries are more flexible than named tuples
    • Lists
      • good when wanting to store several instances of same type of object
      • also keeps order
      • can sort and define own sort functions
    • Sets
      • great at separating groups and letting you know if an item is in it or not
      • must use list if want to sort or order
      • powerful when using multiple sets
      • e.g. union, intersection, symmetric difference, issubset, issuperset, difference,
    • Extending built-ins
      • can either create a new object that holds container or subclass the object and add methods
      • composition usually best if just focused on storing
      • inheritance if want to change the way the container actually works
      • all non-object orientated syntax maps to OO methods underneath the hood
      • use dir(list) to see all special methods
      • help(list.__add__) to see what it does
      • usually if you’re extending a built-in data type may be using wrong thing
  7. Python Object-orientated Shortcuts
    • Len
      • counts number of objects in a container
    • Reversed
      • takes any sequence as input and returns a copy in reverse order
      • returns list_reverseiterator object
      • can use on for loops
    • Enumerate
      • creates a list of tuples with the object and the index
    • Zip
      • takes sequence and creates a new sequence of tuples
      • can pass result in (key,value) format into dict(z)
      • can also unzip into two separate tuples
    • sorted
      • broader than sort (list specific) and works on all iterables
      • can take a key argument that lets you define a function
      • also accepts reverse argument
    • Others
      • min, max and sum also work on sequences. can also use key = lambda for min and max
      • all and any accept iterables and return true or false
      • eval, exec, and compile execute string as code
      • hasattr, getattr, setattr, and delattr allow attribtues on an object to be manipulated
    • Comprehensions
      • supporting iterable protocol means an object has an iter method
      • fancy way of saying it has a next method
      • list comprehensions are faster than for loops
      • can use to filter as well
      • can also use with sets and dictionaries comprehensions
    • Generator Expressions
      • lets you use comprehension syntax without creating a final container object
      • wrap in () instead of [] or {}
      • great when going through large files and space/memory is a concern
      • generally best to use generator expression if don’t need the list, set or dictionary
    • Generators
      • Yield is the key to generators
      • function using it will return and then start where it left off
      • is creating generator objects
    • Method Overloading
      • refers to having methods with same name that accept different sets of arguments
      • is useful when we want a method with the same name to accept different numbers or sets of arguments
      • if we want to make an argument optional, can specify default values using equal sign in parameters
      • cannot have dynamically generated default values because is evaluated when function is interpreted/defined not when called
      • must be careful about passing empty list into default, will only create one list
    • Variable Argument Lists
      • python can also accept an arbitrary number of positional or keyword arguments
      • varargs, specify with a * in the function definition
      • takes any number of arguments and puts them into a list of strings
      • **kwargs arrive into function as a dict. commonly used with setup
      • can have both * and ** in one function
    • Unpacking arguments
      • can also use * to unpack a list in the function call
      • can use ** to unpack a dictionary in function call
      • useful when mapping info that has been collected from user
      • can also add into custom object
    • functions are objects
      • don’t need to wrap methods in objects because functions are already objects
      • can pass around functions as callbacks
    • functions as attributes
      • can also set new function
      • e.g. a.print = fake_print
      • can be confusing to maintain
      • adding or replacing mthods at run time (monkey-patching) is used in automated testing
      • can also be used to fix bugs or add features in third-party code that does not act the way we want it to
      • typically should be avoided
    • Callable objects
      • any object can be turned into a callable by giving it a “__call__” method
      • foo_instance = Foo()
      • foo_instance() #will call the __call__ method
      • functions are callable objects
  8. Python Design Patterns I
    • Decorator Pattern
      • allows us to wrap objects with other objects that alters functionality
      • enhances response of a component that is sending data to a second component
      • supports multiple optional behaviors
      • decorators will do some added processing before or after calling the core functionality
      • mostly used with functions in Python, but can be used with callable objects or classes
      • good when needs to be dynamic
    • Observer Pattern
      • useful for state monitoring and event handling
      • a core object can be monitored by observer objects
      • whenever something changes core object calls an update method letting observers know
      • core doesn’t care what the observers do and observers don’t care what other observers do
    • Strategy Pattern
      • implements different solutions to a single problem each in a different object
      • because python’s first-class functions allow this to be implemented in a more straightforward way
      • can just create a set of top-level functions and pass them around
    • State pattern
      • Allows an object to alter its behavior when its internal state changes
      • goals is to represent state-transition systems
      • need a manager or context class that provides an interface for switching states
      • this class contains a pointer to the current state
      • there is a context class and a multiple state class
      • the state or the context needs to know which other states that it can switch to
    • Singleton pattern
      • In python, usually doing something wrong if using this one
      • basic idea is to allow exactly one instance of a certain object to exist
      • usually some sort of manager class
      • can use __new__ to make sure only one instance is ever created
      • In Python, this pattern can be sufficiently mimicked by using modules
    • Template Pattern
      • common steps are implemented in a base class
      • different steps are overridden in sub-classes to provide custom behavior
  9. Python Design Patterns II
    • Adapter Pattern
      • designed to allow two pre-existing objects to work together
      • sole purpose is to provide a translating job
      • usually create a class as an adapter
    • Facade Pattern
      • simple interface to a complex system
      • there may be a “typical” usage
    • Flyweight pattern
      • Memory optimization pattern
      • usually implement after running into memory problems
      • premature optimization can result in programs that are too complicated to maintain
      • can have a shared model that has properties that other models might all share
      • only store shareable state
      • e.g. you don’t need to instantiate multiple instances of one card object, check if already exists and return it if it does
    • Command Pattern
      • adds level of abstraction between actions that must be done, and the object that invokes those actions normally at a later time
      • in python, can add the command from another object of a class that has the method you need
    • Abstract Factory Pattern
      • multiple possible implementations of a system depending on some configuration
      • e.g. Django returns a set of object relational classes for interacting with specific databases
      • often you can use a separate module for each factory
    • Composite Pattern
      • allows complex tree-like structures from components
      • files have a list of children
      • files and folders can have similar behaviors
      • good for folder/file-like systems, hierarchies, HTML DOM
  10. Files and Strings
    • Strings
      • In python3, strings represented in Unicode, which can represent virtually any character in any language
      • methods available to manipulate strings
      • can also format using braces and ‘{}’.format(‘x’)
      • format can also handle other primitive types, container data structures, or objects
    • Unicode
      • important to be able to convert unicode to bytes
      • can use .decode method to convert an array of bytes
      • decode accepts a string for the name of the character encoding
    • File IO
      • OS’ represent files as a sequences of bytes
      • encoding and decoding lets you deal with the text object
      • passing in ‘b’ lets you open/read/write binary files
      • make sure to close to ensure any buffered writes are written to file
    • Context
      • Open/close files pythonically with “with open(‘name’) as file:”
      • context managers used to properly manage resources, if you don’t close, eventually will crash
    • Storing objects
      • python pickle module allows storage of objects directly in a special object storage format
      • any object can be pickled
    • Serializing web objects
      • JSON is widely used
      • most often for transmitting data from a web server to a Javascript-capable web browser
      • python json module can convert
  11. Testing Object-orientated Programs
    • Testing may be more important in Python because of its dynamic nature
    • Changing code in one area can affect other parts of the program and automated testing can catch this
    • Main Reasons to Write Tests
      • Ensure code is working the way the developer thinks it should
      • Ensure the code continues working when making changes
      • Ensure developer understood the requirements
      • Ensure the code has a maintainable interface
    • Good idea to run tests whenever you’ve changed code to check you didn’t inadvertently break anything
    • TDD (Test-Driven Development)
      • First ensures that tests are written
      • Second forces us to consider exactly how the code is going to be interacted with
    • Unit Testing
      • focuses on testing the least amount of code possible in any one test
      • unittest module and its class TestCase helps to compare values, set up tests and clean up after
      • methods must start with ‘test’
      • each test should be independent of other tests
      • key to writing good unit tests is to keep them as short as possible
      • if you can’t break into such testable units, probably sign your design needs rethinking
    • Assertion methods
      • assertEqual
      • assertNotEqual
      • assertTrue
      • assertFalse
      • assertRaises
      • each method accepts an optional argument named ‘msg’ which can be included in the error message
    • Additional assertion methods in Python 3.1
      • assertRaises can take advantage of with
      • assertGreater, assertGreaterEqual, assertLess, assertLessEqual
      • assertIn, assertNotIn
      • assertIsNone
      • assertSameElements (checks items are same regardless of order)
      • assertSequenceEqual: enforces order
      • assertDictEqual, assertSetEqual, assertListEqual, assertTupleEqual: also checks container objects are the correct type
      • assertMultilineEqual: checks two multiline strings are equal
      • assertRegexpMatches
    • Reducing boilerplate and cleaning up
      • sometimes may need to do a certain setup multiple times
      • can use setUp method on TestCase class to do initialization for each test e.g. self.blank = blah
      • setUp is called individually for each test
      • tearDown method can also be used for cleaning up, useful if test involves more than just letting an object be garbage collected
      • Usually group test methods into separate TestCase subclasses depending on what setup code they have in common
    • Organizing and Running Tests
      • doesn’t take long for tests to grow very large
      • Can collect groups of TestCase objects or modules into collections called TestSuites
      • however, most programmers can use test discovery which automatically finds and run tests with the discover module
      • looks for any names that start with the characters ‘test’
      • if it finds any TestCase or TestSuite objects it will execute them
      • just run based on whatever version you have
    • Ignoring broken Tests
      • tests may fail under some circumstances
      • python provides decorators to mark tests as expected to fail
      • decorators: expectedFailure(), skip(reason), skipIf(condition, reason), skipUnless(condition, reason)
    • Testing with py.test
      • unittest module is very verbose and based on JUnit test framwork for Java
      • py.test and nose are popular frameworks that follow python convention
      • py.test doesn’t require a class and lets any properly named function to behave like a test
      • just uses assert statement to verify results
      • looks for folders with ‘test_’ and executes any function that starts with ‘test’
      • also any classes that starts with ‘Test’ will have any methods that start with ‘test_’ will also be executed
      • Classes are still useful for organizing and setting up initial conditions, don’t need to pass in any special object
      • only allows print statement if test fails – very useful don’t need to remove
    • One way to do Setup and Cleanup
      • if writing a class-based test, can use setup_method and teardown_method
      • they both accept an argument for the function object representing the method being called
      • setup_class and teardown_class accept class in question
      • setup_module and teardown_module are run once, good for creating sockets or database connections
      • need to be careful to not introduce dependencies if the object being set pu stores state
    • Completely different way to set up variables
      • can use funcarg, which will be passed into the test as a parameter
      • usually want to define in a file called conftest.py to separate config from the test
      • funcargs must be named ‘pytest_funcarg__’ + <valid identifier> where the identifier is the parameter for the test functions
      • funcarg is created afresh for each call
      • request object gives us flexibility with managing modules, cls, and functions as well as with setup and teardown
      • can cache setups if have an expensive setup that you want to use multiple times
    • Test skipping with py.test
      • can skip any tests with py.test.skip function
      • if in a function, will skip the function
      • if in module, will skip tests in the module
      • if in funcarg, will skip all tests that call that funcarg
      • usually only want to skip tests if certain conditions are met
      • usually use in an if statement
      • usually test python version, operating system, or some_library version
      • @py.test.mark.skipif(“executable code that reduces to a Boolean”)
      • @py.test.mark.xfail: expected to fail
    • py.test extras
      • very powerful tools w/ more capabilities
      • distributed testing (across a network)
      • numerous plugins
      • extensive customization
      • passing -x or –exitfirst will exit after first failure
      • –pdb: instead of failing drops to a python debugger shell
      • –looponfail or -f (only py.test xdist plugin is installed): automatically rerun itself after failing code is encountered. lets you fix, save and will run
      • -k (important): accepts a keyword to search for tests. used to run specific tests that contain given keyword.
    • How much testing is enough
      • onus of designing complete test suites lies with the programmer
      • code coverage: number of lines of code that are executed by the program
      • figleaf and coverage.py are tools to figure this out
      • e.g. “coverage run coverage_unittest.py”
      • will create a .coverage file that holds data on the run
      • “coverage report” command to see it
      • tells how many lines of code in file and how much was executed
      • if you pass in -m option will tell you which lines
      • “coverage html” shows a fancier interactive HTML report viewable on the web browser
      • just because you have code coverage doesn’t mean it was tested properly
  12. Common Python 3 Libraries
    • SQLAlchemy
    • TkInter: graphical library
      • construct widgets and command them
    • PyQt: another graphical toolkit
    • XML:
      • may have to interact with XML data from other programs
      • SAX: can parse XML document on the fly, but can be unwieldy, good for streaming and working with huge documents
      • DOM: treats document like  tree of connected nodes.
      • ElementTree: allow XML documents to be treated like Python objects
      • lxml: allow XML documents to be treated like Python objects
    • ElementTree
      • represents entire XML document in memory
      • can also construct XML
    • lxml
      • more advanced tool
      • parse invalid SML
      • advanced XPath
      • CSS selectors
    • CherryPy
      • web application server
      • is not a full framework
      • does not supply templating and data storage
    • Jinja for templating
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s