Table of Contents
- Python
- History
- Python Structure
- Building Main
- Variables
- Underscore Prefixes
- Easy Commands
- Operators
- Truthiness and Falsiness
- Conditionals and Loops
- Missing Operators
- Functions
- Parameters
- Assert and Exception Handling
- Array Like Structures
- Lists
- Tuples and Strings
- Python and OOP
- Creating a Class
- Self
- Inheritence and Polymorphism
- Super
- Credit
Python
Taking over the world, rapidly became the number one most popular language analytically
- Python is an extremely versatile language
History
Began development in 1989
- started as a hobby over Christamas vacation
- appeal to UNIX and C programmers
Python Structure
- Python does not follow ‘{}’ code blocking
Python identifies code blocks through common tab structure
- Python is going to force you to be structured
- Even one space off can mess up your program
- Be wary of tool usage
- Use the tab key
- Do not mix tabs and space when defining a code block
- Python uses 4 space as indentation by default
Syntax Structures
- One of the really nice things about Python Structure is a more regular syntax
- The major structures are all very similar, close to the same as english language
Building Main
{
def main():
print("Hello World")
if __name__ = "__main__":
main()
}
- Now we have a main function
- However, we need to be aware of the way that python reads and understands code. Python does not read code like other interpreters (java). The code is read from top down. Therefore this would happen
{
def main():
print("Hello World!")
print("This is executed first\n")
if __name__ = "__main__":
main()
}
Output: This is executed first Hello World!
print("Hello","this","is","test")
Output: Hello this is test
{
var1 = 1
var2 = 2
var3 = 3
print(var1, var2, var3)
}
Output: 1 2 3
Variables
- There is no command for creating a variable in Python
- Creating variables in Python is done through the assignment operator ‘=’
Identifiers can start with an uppercase/lowercase letters
- cannot start with _
All other identifiers start with a lowercase letter
- Starting an identifier with a single leading underscore means that it is protected
- Using two leading underscores triggers the mangling mechanism and a strongly private modifier
Underscore Prefixes
It is a python convention to prefix _ or __ varibales to be private/protected
- _ as the first character in a scall is an “implementation of detail”
- This is the python equivalent to Protected, which is semantic and offers one language feature
'__' triggers a name mangling mechanism
- protects a name from being accidently overriden
Data Types
Python is Dynamically and Strong typed
- Often known as duck typing
- Strong typing means that vars act as their type and not in unexpected ways
- Less or no data coercion
- Strings don’t magically become numbers
- Required explicit conversions
- Dynamic Typing means that vars are not fixed from one type line to line
- Not necissarily contradictory
- Strong speaks to how the variable is used, not to how it is changed
- We can change from line to line and how we change it will link it to that data type
Variables will remain strongly typed
var1 = 1
is an integer
However we can convert this integer to a string
print(str(var1))
We can change a variable between different types without classifying the change. Use quotes to change from int to string
{
var1 = 1
var1 = "foo"
}
- This var just changed from an integer to a String
Nuances
When declaring vars you want to create with a default value to represent this data type
{
myNum = 100 #Integer
myNum = 100.0 #Float
myNum = "100" #String
myNum = 0 #Integer
myNum = 0.0 #Float
}
- Decimal will always create a float value
Easy Commands
To get basic information from the user we use the input()
command/function
input()
is a value returning function so it will be coupled with an assignment statement
Example.
{
name = input("What is your name? --> ")
}
Be Careful!
- Everything that is put through the input command is evaluated as a String so we would need to cast this variable to something else once formatted
Example.
{
num = input("Choose a number? --> ")
}
This is something different in Python3. In Python2 this wasn’t and issue and python used to make the decision on the type of variable for you
Operators
Math Operators
There are a few differences but mostly the same
-
- ; addition
-
- ; subtraction
-
- ; Multiplication
- / ; Floating Point Division
- // ; Integer Division
- ** ; Exponent
Bitwise Operators
Python allows us to manipulate binary as well and gives standard bitwise operators
Operator | Description | |
---|---|---|
& Binary AND | Performs a bit by bit AND if the bits are 1 in the same spot | |
Binary OR | Performs an OR – 1 in either results in a 1 in the result | |
^ Binary XOR | XOR if there is a 1 in either, but not both there is a 1 in the result | |
~ Binary Ones Complement | Flip all the bits in the variable | |
« Binary Left Shift | The left operands value is moved left by the number of bits specified by the right operand | |
>> Binary Right Shift | The left operands value is moved right by the number of bits specified by the right operand |
Logic Operators
Logic operators are used by the word. Rather than using || or && we type the word ‘or’ and ‘and’
- True and False keywords in python are capitalized
Operator | Description | Example |
---|---|---|
and | Logical AND | True and False = False |
or | Logical OR | True or False = True |
not | Logical NOT | not True = False |
is | Evaluates to True if the two vars point to the same object | obj1 is obj2 |
is not | Evaluates to True if the two variables do NOT point at the same object | obj1 is not obj2 |
Truthiness and Falsiness
False Things
Many things can be considered false. Follow this structure.
- if it is representative of the idea of ZERO… then it is false
True Things
- Easy to lock down
-
if it isn’t false, then it is true
- be aware of what things return within our code
- this is a problem in C/C++ where the ‘=’ operator will return *this
Conditionals and Loops
Standard, however some important differences
- if
- Else
- Else If
- While
However it is missing:
- Do While
- For
{
def main():
print("Hello")
grade = int(input("Enter your grade: "))
if grade >= 90:
print("A")
elif grade >= 80:
print("B")
elif grade >= 70:
print("C")
elif grade >= 60:
print("D");
else:
print("E")
if __name__ == '__main__':
main()
}
While Loops
While loops are exactly the same as other languages
- while something is true, do the loop body
- while continues to follow the colon-tab structure
{
count = 0
while count < 10:
print(count)
count+=1
}
Break and Continue
- break and continue are part of the python language as well
- However, using them sparingly is advised. They can eaily crutch bad programming practices
As Author Matthew Read noted:
Bad programmers speak in absolutes. Good programmers use the clearest solution possible (all other things being equal). Using break and continue frequently makes code hard to follow. But if replacing them makes the code even harder to follow, then that’s a bad change.
Missing Operators
In Python there are no:
- Switch-Case Statements
- must use if-elif-else chain
- Post-Test Loop (Do-while)
- Rewrite loops as pre-test loops
- Do priming read before the loop and go
- For Loop… kind of
- For loops are different
These loops don’t work like we have seen them before. In languages such as Java we write
for (int i=0; i<5; i++){
}
}
However, in python we write them as:
{
for i in range(5):
[code]
}
Functions
Coding with functions and coding with methods are two different things
Here are the main differences
Method
- Belongs to a class
- Important distinction
- Methods are generally expressed behaviors of a class/object
- Semantically tied to the class they are a part of
- Can only be acces via an object
- Unless they are static
Function
- Does NOT belong to a class/object
- Expresses a useful idea or operation
- Generally semantically tied to the program as a whole rather than the behaviors of a piece of it
- Can be called anywhere in the program
This is important for Python because it can act as many of these. Works with methods and functions
- Java is different in this respect and can only create methods
- C++ and Python can create functions
Functions in Python
__main__
was already our first function- Here we can now formalize the syntax
{
def <function name>(<param list>):
<body>
}
- Like many languages a function must be defined before you use it
- Unline javascript, functions are not hoisted
- They are interpreted n place which means if they are not defined by the time the interpreter gets to the call, there will be an error
- Names can be any valid identifier
- The param list is just a series of variable names separated by commas
- which means that params are untyped until the function call
- The func body is tabbed over and un-tab indicates body is done
- Further functions within the same will be further tabbed
- Single values can be returned with a return statement
- Can be multiple return statements but we can only have one final return
{
def isEven(value):
if (value % 2 == 0):
return True
else:
return False
}
What if we call a non-numerical value here?
- Wrong variable type so we would have an issue here
Parameters and Python
Python passes parameters in a similar manner to Java. Primitive and immutable types are passed by value Mutable objects are passed by object reference
- AKA ‘Passed by Pointer’
- When obj ref is passed that means we can change the object but can’t reassign the object reference
- Pass in an array
- You can change the contents of that array
- You cannot have that array store a brand new array
- Pass in an array
Parameters are like every other variable
- While semantics can be added we can be more explicit with code
- Example
def isEven(value:int):
- Example
This is not enforced as syntax Passing a float will not raise an error
{
def isEven(value:int):
assert isinstance(value, int)
print(value)
if(value % 2 == 0):
return True
else:
return False
}
Python does not allow for overloading
- This means giving the same function multiple definitions based on different parameter lists
- Different languages have different rules for it, but generally all of them require param list changes
This allows for the ability for Default Parameters
- these params can also be known as Optional Parameters
When a param is defined we use the ‘=’ operator
{
def addNumbers(first, second, third = 0, fourth = 0):
return first + second + third + fourth
addNumbers(1,2)
addNumbers(1,2,3)
addNumbers(1,2,3,4)
}
- This is similar to how the
range
function worked earlier and details how we don’t have to always use all parameters
What are the rules here?
Python has a lot of ways to get around its own rules We can use “Keyword Arguments” Parameters are filled from left to right- How can we skip to the fourth? Default params must go from left to right as well
We can change the order of calling parameters if we know the names
{
def printinfo( name, age ):
print "Name: ", name
print "Age: ", age
return
printinfo( age = 52, name = "Billy")
}
Unknown/Arbitrary/Variable-Length Param
- Sometimes we want to make a function that doesn’t know how many params are going to come in?
- We can accomplish this with an ‘ * ‘ as a prefix to a parameter name
- The param will now contain a Tuple that contains those values
- The variable-length param should generally be the last in the parameter list
- Except when we are using Default parameters and Keyword use only
{
def addThemAl(*numbers):
total = 0
for value in nums:
total += value
return total
print(addThemAll(1,2,3))
print(addThemAll(1,2,3,4,5,6,7,8,9))
}
Revisiting Print()
print() is actually more versatile than earlier
- full syntax =
print(*objects, sep= ' ', end='\n', file=sys.stdout, flush=False)
sep, file and flush can be set via keyword args
- sep; allows us to change the separator between objects, defaults to ‘ ‘
- end; allows us to change what is outputted at the end of the print, defaults to a newline char “\n”
- file; allow to change the target of the output
- must have write(string) method
- can be used for basic File output
- flush; True or False, specifies if the output is flushed or buffered (False)
Assert
The assert command is essentially sanity check
assert <condition>
assert <condition>,<error message>
Basically a way to force an error in your code if a condition is not met
- This is an ALL STOP and gives an AssertionError
Exception Handling - Raising an Exception
- Instead of using assert, we can Raise an exception
- Known as throwing an exception
- isinstance can still be used
{
def isEven(value:int):
if not isinstance(value, int):
raise TypeError("value expects integer")
print(value)
if(value % 2 == 0):
return True
else:
return False
}
- Python has a large list of built in exceptions
- Very built and largely accessible
Array Like Structures
Python comes with a handful of data structures built into the language
- Unlike Java and others, these are generally default language feature and require no imports or libraries
Containers
Lists
Refers to a list collection type. Often called an array because it is similar, however… the list is NOT an array as we might be used to
- It is actually, depending on the interpreter you are using, structurally different The python list Variable Length Array is similar to Arraylist in Java
- But not in the bad C way
- Allows for an open ended array. No set length value
Java ArrayList is underpinned by an Array, so it isn’t a Python list
- An array is of fixed size with a chunk of memory that stores multiple variables through the same name
- The index of each variable is achieved via pointer arithmetic
- The ArrayList is a managed array class
- Each ArrayList is an object
Array | ArrayList/PythonList |
---|---|
Fixed in Size | Managed Array |
Managed by programmer | object will replace underpinning array |
Can’t shrinkand grow, can only be replaced | Programmer has no say in size after creation |
Memory is managed by the programmer | Automatically grows |
Can waste memory |
Why is this so important?
- Like using ArrayLists in Java there is an inherent give and take to using lists
- We’re going to give up control and possibly effeciency
- Gain a dynamic feeling data structure that guarantees O(1) runtimes
- Since we often don’t care about memory efficiency as much in Python – we’re ok with this trade-off
Creating Lists
To create a list we simply assign a [] to the variable This [] can contain init values if we like:
myList = []
- creates an empty list
myList = [1,2,3,4]
- list containing 1, 2, 3, 4
Construct a list with
{
myList = list(< iterable >)
}
Lists are Objects
- append(x)
- adds item to end of list
- extend(
) - adds all items from an iterable structure to end of list
- remove(x)
- find and remove x from list
- change the size
- pop( [index] )
- remove last item of the list and return
- index provided does the same at the index
- reverse()
- reverse the list without return
- sort()
- sorts the data if it can be sorted
With these methods lists can be used as a Stack or a Queue
- Append and Pop give it a stack like behavior automatically
- However, you can pop(0) to get a queue like behavior
Tuples and Strings
Tuples are immutable collection. Once built, they cannot change
- They don’t shrink or grow
- You can’t change the data contained within them Tuple syntax is pretty much identical to List syntax. The difference is that tuples use () for declaration syntax.
- myTuple = (1,2,3,4)
- But uses [] for indexing–print(myTuple[1])
Tuples have a key feature - they are HETEROGENEOUS
- We can mix data types within them
- Generally get used to represent “records”
- Can also be used to return multiple values from a function
Strings are what you expect them to be
- Strings are a mutable collection of characters that represent text
- Like Java, they are Objects
String Operators
- [index] - Gets a specific character
- [start:finish] - Gets a substring
- [start:] - Substring from start to end
-
-
- concat operator
-
-
-
- allows us to ‘multiply’ a string
-
{
print("Hello"*2)
}
Common Methods
- count(value, start, end)
- returns number of times a substring appears within string
- pattern analysis
- find (value, start end)
- returns the index of a substring found in a string
- swapcase()
- returns a string with all the ltter cases flipped
- split(sep, maxsplit)
- returns a list of substrings delimeted by the separator (space by default)
- upper()/lower()/title()
- changes cases of string
- strip(char)
- removes a set of characters from the string
Python and OOP
- Python is an object oriented language, but ut has a lot of differences from what you might be used to in Java
- Python’s OOP is less robust overall and has a very different feel (more similar to C++)
Differences
There’s a dearth of keywords in Python
- No keywork for creating variables
- No keywords for visibility modifiers, methods over functions, static etc.
Inheritance and Polymorphism is supported
- Override methods easily
Encapsulation is partially supported. This means that coding python OOP requires a different pattern.
Creating a Class
A class in Python follows our same Python Code Block Pattern that we see in Ifs/Loops/Conditionals. We use the keyword class followed by class name
class Box:
Class Constructor
In python, we don’t make contructors from the Class Name.
To make a constructor we define the __init__
function
{
class Box:
def __init__(self):
pass
}
- The Box class can now be constructed
- Does nothing at the moment
Basic Anatomy
- Class Attributes
- Essentially the same as static properties
- Shared at the class level
- Shared by all objects of the class
- Instance Attributes
- What we usually class Properties of a class
- These are defined during the init method call
What do you do with methods?
- Each object is unique
- Each object has its own properties and each call to a method from a unique object is different
- methods are compiled separately in the same way that a function would be
How do we keep each call unique?
this
informs what properties are available and other methodsthis
is usually hidden- often it is considered a readability or clarity feature more than anything else
- In python this is NOT automatic
-
the keyoword for
this
in python is actuallyself
- it is the first parameter in EVERY method
- including the constructor
Self
Meaningful tab structure AND required use of self
- Since var creation occurs via the assignment statement, we need to use self to specify and bind the variable to an object
- Implication
- Don’t build properties like we do in Java
- All instance properties like we do in Java
Confusion and Problems
Each method requires the self parameter first Creation of properties happen in the init method
Instantiation
- Instantiating an object is simple
- Class the class name as a function and pass in the appropriate parameters
Destructor
- Python collects garbage
- Gives us more control over the memory management
Unlike Java we have a command to explicit delete an object
- this marks it for garbage collection This means we can then supply a Destructor for our class
- Clean up other memory the object might be using
- Gives instructor on how to destroy an object
- Called when the object is deleted
Creating a destructor
{
def __del__(self):
#delete things
}
This gives python greater memory effeciency
Other things we can Overload
Method | Description ——-|——————————— str(self): | This defines a ‘toString’ for the class, making printing objects easier add(self, other): | This overloads the ‘+’ operator for the class len(self): | Overloads a len() function for length abs(self): | Defines how the class responds to absolute value getitem(self, index): | lets your class respond to []
There are dozens of methods you can overload to customize your class
- every math operator and their shortcuts
- Byte to string conversions
- Relational Operators
Inheritence and Polymorphism
Inheritence
- Python allows for multiple inheritence Fundamentally different than Java
-
Java enforces single inheritence and uses Interfaces to simulate some of the features of Multiple inheritence
- The child class will have access to all the members of all of its parents… which also exists in C++
Basic Inheritence
Class are just ‘passed in’ with inheritence from the parameters list
class Child(parent)
To accomplish multiple inheritence
class Child(Parent1, Parent2, Parent3)
Constructors and Inheritence
Parent constructors must be called
- Objects in OOP are essentially conglomerations of parent objetcs and the new stuff that child objects bring
- Build the portions of the child that IS A parent class
super()
This allows us acces to the first param of the child class (first parent) Purpose:
- Used Super in Java
- Allows us to invoke parent behaviors
Constructor is not invokes automatically, and must be invoked explicitly
{
class A:
def __init__(self):
print("A")
class Child(A):
def __init__(self):
print("child")
ch = Child()
}
In the above function the outcome will only print ‘child’. The A constructor would not be called.
However, we can overcome this with:
{
class A:
def __init__(self):
print("A")
class Child(A):
def __init__(self):
super().__init__()
print("Child")
ch = Child()
}
Here we would get “A” and “child”
Multiple Inheritence Super
The super() function only reference the first parent in the inheritence When we have multiple inheritence, we have to callout the aprents explicitly and invoke their init
{
class A:
def __init__(self):
print("A")
class B:
def __init__(self):
print("B")
class C:
def __init__(self):
print("C")
class Child(A, B, C):
def __init__(self):
A.__init__(self)
B.__init__(self)
C.__init__(self)
print("child")
ch = Child()
}
This will output A, B, C and Child
Python will not build the parent portion of a child class if you do not invoke the init of the parent
- Either through super or through the class
Parent Constructon is Required In multiple inheritence just calling super().init() will not build all of the parents
- Will create an error message
Methods vs Properties
Polymorphism
Essentially change/difference at the same level of inheritence
- same things many forms is often the summary We can have a base class like animal and many different animals
- Dogs –> Class –> Breed