Classes
class Account(object) : # inherits object directly
instanceCount= 0 # like static variable in java
#this is similiar to java constructor, called automatically during creation : Account("assaf") def __init__(self, balance, someBool=true):
self.Balance= balance#note: no need to define them before, nice!!!
#this is similiar to java constructor, called automatically during creation : Account("assaf") def __init__(self, balance, someBool=true):
self.Balance= balance#note: no need to define them before, nice!!!
self.SomeBool= someBool #public style
self._XProtected = 5 # one '_' prefix is like java-public, but the programmer ask politly.
self.__Yprivate = 8 # two '_' prefix is like java-private. you 'll get exception when accessing.
Account.instanceCount +=1
#destructor (usually unused, like in Java) called when no reference exists any more .
#for example by using x=None, or explicit calling del(x)
def __del__(self):
Account.instanceCount -=1 #static variable: note the usage of Account. and not self.
#like the ToString method. optional, of course
def __str__(self):
return "balance: %f".format(self.Balance)
#regular method
def deposit(self, x): #note, when calling it "self" is not needed
self._XProtected = 5 # one '_' prefix is like java-public, but the programmer ask politly.
self.__Yprivate = 8 # two '_' prefix is like java-private. you 'll get exception when accessing.
Account.instanceCount +=1
#destructor (usually unused, like in Java) called when no reference exists any more .
#for example by using x=None, or explicit calling del(x)
def __del__(self):
Account.instanceCount -=1 #static variable: note the usage of Account. and not self.
#like the ToString method. optional, of course
def __str__(self):
return "balance: %f".format(self.Balance)
#regular method
def deposit(self, x): #note, when calling it "self" is not needed
self.Balance += x
Usage:
account = Account("assaf")
account._XProtected = 666 #works, but '_' it means the programmer asked you not to do it
account = Account("assaf")
account._XProtected = 666 #works, but '_' it means the programmer asked you not to do it
print( account._XProtected) --> 666
print( account.__Yprivate) --> AttributeError
print (account._Account__YPrivate) --> 8 #showing you there is no real way in python to defend against this. if someone want's, he can access it anyway
print (account._Account__YPrivate) --> 8 #showing you there is no real way in python to defend against this. if someone want's, he can access it anyway
inheritance and static variables
class Counter:
instanceCount = 0
instanceCount = 0
def __init__(self):
type(self).instanceCount +=1 # and not Counter.instanceCount, cause it will be all sons.
def __del__(self):
type(self).instanceCount -=1
class Account(Counter):
def __init__(self, x,y,z):
Counter.__init__(self) #explicit call is needed!
type(self).instanceCount +=1 # and not Counter.instanceCount, cause it will be all sons.
def __del__(self):
type(self).instanceCount -=1
class Account(Counter):
def __init__(self, x,y,z):
Counter.__init__(self) #explicit call is needed!
class MultipleInherit(Counter, Shouter):
def __init__(self, x,y,z):
Counter.__init__(self)
Shouter_init__(self, y)
storage optimization (__slots__)
each instance has a built-in __dict__ hashmap, which contains all the dynamic memebers. It means that you can always add members to a class, but it's heavier in storage on the RAM.
account = Account("assaf")
account.dynamicNewMember = 8 #works just fine
If you instantiate millions of these instances, instead of using the built-in __dict__, you can use a tighter static structure. Note: Don't optimize this way unless you have millions of instances.
Use __slots__ and define them before hand , by name , like:
def AccountWithLessStorage:
__slots__ = ['Balance', 'someBool', '_XProtected', '__YPrivate']
account = Account("assaf")
account.dynamicNewMember = 8 #works just fine
If you instantiate millions of these instances, instead of using the built-in __dict__, you can use a tighter static structure. Note: Don't optimize this way unless you have millions of instances.
Use __slots__ and define them before hand , by name , like:
def AccountWithLessStorage:
__slots__ = ['Balance', 'someBool', '_XProtected', '__YPrivate']
#everything else in the class is exactly the same, including usage in __init__
MetaClass , annotations and Reflection
java reflection-like operations is much easier in python,
instance.__dict__ # is a dictionary of the members (variables and methods), so calling the method append on a list can be done "in-reflection" very easily.
lst = [ 1 , 2 , 3 ]
non-reflection: list.append(4)
reflection: list.__dict__["append"](lst, 4) # the 1st parameter is for instance method is "self"
Use decorators to wrap a method
Use metaclass for decorators like count call/timer/logging.
instance.__dict__ # is a dictionary of the members (variables and methods), so calling the method append on a list can be done "in-reflection" very easily.
lst = [ 1 , 2 , 3 ]
non-reflection: list.append(4)
reflection: list.__dict__["append"](lst, 4) # the 1st parameter is for instance method is "self"
Use metaclass for decorators like count call/timer/logging.
No comments:
Post a Comment