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)