class aClass defines a new data type,
aClass anInstance()
creates an instance,id()
and the corresponding memory space
. operator
#!/usr/bin/env python3
# self is the default reference for an instance
class Simple:
data = 1.0
def setData(self, newData): # a member function
self.data = 0.0 if newData<0.0 else newData
# self.data = newData
def aboutClass(preString): # a static function
return preString + " A simple class!"
# () default constructor (without arguments)
c1 = Simple() # creating an instance
c2 = Simple()
c2.setData(3.0) # calling a member function
print("c1/c2 data : ", c1.data, c2.data)
print("c1 type : ", type(c1))
print("c1.data type : ", type(c1.data))
print("id(c1) : ", id(c1))
print("id(c2) : ", id(c2))
print()
print(Simple.aboutClass("# main :: ")) # calling a static function
dir(): listing of magic class methods
#!/usr/bin/env python3
# a pretty empty class
class empty:
pass # passing (do nothing)
# dynamic creation of new attributes for an existing instance
# -- bad programming --
empty.name = "Alice"
empty.birthDate = "2025"
print("name/date : ", empty.name, empty.birthDate)
print()
print("listing of class magic functions")
print("includes user defined attributes")
print()
for mF in dir(empty): # dir: directory of magic methods
print(mF)
__new__(): magic class method implicitly
called when a new instance is created __init__(): called
when a new instance has been created __del__: destructor, called when
instance is deleted
__dict__: the dictionary of attributes
(of an instance)
del: deletes classes or attributes
#!/usr/bin/env python3
# 'self' could be replaced, e.g. by 'this'
class testInit:
def __init__(self, name, age=None): # defines 'self'
self.name = name
if age==None:
self.age = 0
else:
self.age = age
def __del__(self): # destructor
print("deleting an instance of ", self.__class__.__name__)
def hello(self):
print("Hello for the first time\n")
def hello(self): # overides first definition
print("Hello for the second time\n")
def nothing(): # just a function
print("| entering nothing")
cc = testInit("Julia")
print("| leaving nothing") # destructor called by default
print("*******************************")
print("instance creation in a function")
print("*******************************")
print()
nothing()
print()
print("*************************")
print("basic constructor testing")
print("*************************")
c1 = testInit("Julia") # both constructors possible
c2 = testInit("Alice", 10)
c3 = testInit(age=33, name="Kenys") # calling with keys
c1.hello() # which one is called?
print("c1 : ",c1.name, c1.age)
print("c2 : ",c2.name, c2.age)
print("c3 : ",c3.name, c3.age)
del c1, c2, c3 # deletes them
print()
print("***************")
print("__new__ testing")
print("***************")
c4 = object.__new__(testInit) # object without attributes created
print(c4.__dict__) # dictionary of attributes
c4.__init__('John') # create attributes, don't call twice
print(c4.__dict__)
print()
print("c4 : ",c4.name, c4.age)
# print(dir(c4)) # for comparison
#!/usr/bin/env python3
# a class acting as parent class
class Person:
"docstring of Person class"
def __init__(self, first, last):
self.firstName = first
self.lastName = last
def printName(self):
print(self.firstName, self.lastName)
# a child class of 'Person'
# calling '_init__' of parent class
class Student(Person):
"docstring of Student class"
def __init__(self, ff_name, ll_name, studentNumber = None):
super().__init__(ff_name, ll_name)
if studentNumber==None:
self.studentNumber = 0
else:
self.studentNumber = studentNumber
p1 = Person("John", "Doe")
p1.printName()
s1 = Student("Jane", "Ark")
s1.printName() # inherited
print()
print(p1.__doc__) # docstrings
print(s1.__doc__) # docstrings
print()
@decorator implicit decoration
#!/usr/bin/env python3
import math
#
# a nested function,
#
def outer(x):
print("# in outer", x)
# x += 10
def inner(y):
print("# in inner", x, y)
return x + y
return inner # outer returns inner
add_five = outer(5)
result = add_five(6)
print("# in main ", result)
print(add_five)
print()
print("#==========================")
print()
#
# functions as objects
#
def add(x, y):
return x + y
def times(x, y):
return x * y
def calculate(func, x, y):
return func(x, y)
print("# adding ", calculate(add , 4, 6))
print("# multiplication ", calculate(times, 4, 6))
print()
print("#==========================")
print()
#
# decorators
#
def addSomething(anyFunc):
def inner(x):
print("# inner, doing something ")
return anyFunc(x)
return inner
@addSomething # decorating the following function
def newExp(x):
return math.exp(x)
print("# calling newExp ", newExp(7.0))
#!/usr/bin/env python3
import math
from funcy.debug import print_durations
from funcy.debug import log_durations
# may need to be installed
# pip install funcy
# funcy -- functionaly Python
def useLogMessage(log_message):
"""do something with the log message,
like logging to a file"""
print("# time logging: ", log_message)
@log_durations(useLogMessage) # for any function call / block
# @print_durations() # directly to console
def hardWork(nIter):
xx = 0.0
for _ in range(nIter):
xx = 1.0/(1.0+xx)
return xx
golden = 0.5*(math.sqrt(5.0)-1)
# actually, the golden ratio is
# 0.5*(math.sqrt(5.0)+1)
print(hardWork(int(1e5)))
print(hardWork(int(1e7)))
print(golden)