Yaolong Huang
In Python, everything is an object.
Everything is an instance of a class.
# We can use type() to check the type of every object.
>>> type(1)
<type 'int'>
>>> dir(1)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__getattribute__', '__getnewargs__', '__hash__',
....]
>>> a = 1
>>> a.__abs__
<method-wrapper '__abs__' of int object at 0x985ef38>
>>> def test():
... pass
>>> type(test)
<type 'function'>
>>> test.__hash__
<method-wrapper '__hash__' of function object at 0xb7f8aae4>
To check whether a object is of certain class,
use isinstance.
>>> isinstance(1, int)
True
>>> isinstance(1, bool)
False
>>> class Base(object):
... pass
>>> b = Base()
>>> isinstance(b, Base)
True
You can use class keyword to define a new class.
class Base(object):
pass
b = Base() # this creates a new object of class Base and assign it to b
To define a method in a class,
you just define the method like a normal function.
But you should add a self parameter before other parameters.
class Base(object):
def hello(self, msg):
print 'hello,', msg
b = Base()
b.hello('world!')
class Base(object):
def hello(self, msg): # self?
print 'hello,', msg
What? You don't know what's self ?
self is yourself. It's like this in C++.
And yes, you have to write self yourself.
Python won't do it for you.
To define a data member in a class, what should you do?
You do nothing, just assign a value to it.
class Base(object):
def hello(self, msg):
self.msg = msg
print "hello,", self.msg
# and you can use it once it has been defined.
b = Base()
print b.msg # NO, it's not defined yet.
b.hello('world!')
print b.msg # YES, it's been defined.
How about public/protected/private in C++?
Python do not provide these facilities.
But Python has a convention to do this.class Base(object):
def hello(self, msg, times):
self.msg = msg # members without prefix is public
self.__times = times # members with "__" prefix is private
for _ in range(self.__times):
print "hello,", self.msg
b = Base()
b.hello('world!', 2)
b.msg # this is public, so you can use it outside.
b.__times # NO, it's private, so you cannot use it.
What about protected?
class Base(object):
def hello(self, msg, times):
self.msg = msg # members without prefix is public
self._times = times # members with single "_" prefix is protected
for _ in range(self._times):
print "hello,", self.msg
b = Base()
b.hello('world!', 2)
print b._times # What?
Yeah, you still can use protected member outside.
In Python, protected member is a convention, you can ignore it.
But once you ignore it, Python will fool you.
The same access rule applies to methods of a class.
class Base(object):
def hello(self, msg, times): # this method is public
self.msg = msg
self._times = times
def __print_msg(self): # this method is private
for _ in range(self._times):
print "hello,", self.msg
b = Base()
b.hello()
b.__print_msg() # NO, this is a private method
But note that method which both begins and ends with "__" is not private. It's special method.
What about constructor in C++?
class Base(object):
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.__arg2 = arg2
b = Base(1, 2) # this will call __init__
print b.arg1
As you see, __init__ begins and ends with "__", so it's special.
As mentioned before, we can create a new object of a class by "calling" the class.
And in Python, you can add attributes to an object after it's created.
class Base(object):
pass
b = Base()
b.data = 1 # This is okay.
print b.data
And this is a way to create a struct in Python.
If you add a member/function to a object, other objects of the same class will not be affected.
class Base(object):
pass
b1 = Base()
b2 = Base()
b1.data = 1
print b2.data # NO, this does not work.
b1.fun = lambda a: a + 1
print b1.fun(2) # this is 3
print b2.fun(2) # NO, this does not work.
Remember everything is object in Python?
Guess what?
Class in Python is also an object of certain class.
>>> class Base(object):
... pass
>>> type(Base)
<type 'type'>
>>> type(type(Base))
<type 'type'>
As you can see, a class is an instance of "type" class.
And yes, you can use a class as an object.
Base1 = Base
b = Base1() # This is okay.
Miss inheritance? Actually we have used inheritance before.
class Base(object):
pass
As you can see, the parent class is object.
If you want to derive anther class, just write it between "()".
class Derived(Base):
pass
Pylymorphism is implemented as virtual function normally.
In Python, every method in a class is virtual.
class Base(object):
def hello(self):
print "Base: Hello"
class Derived(Base):
def hello(self): # overrides Base.hello
print "Derived: Hello"
b = Base()
b.hello() # this will print "Base: Hello"
d = Derived()
d.hello() # this will print "Derived: Hello"
But private methods are not virtual.
class Base(object):
def hello(self):
self.__print("Hello")
def __print(self, msg):
print "Base:", msg
class Derived(Base):
def __print(self, msg): # DOES NOT override Base.hello
print "Derived:", msg
b = Base()
b.hello() # this will print "Base: Hello"
d = Derived()
d.hello() # this will also print "Base: Hello"
What about the constructor?
Because constructor is special method, we can call it directly.
class Base(object):
def __init__(self):
self.a = 1
class Derived(Base):
def __init__(self):
Base.__init__(self) # this calls Base's constructor
self.b = 2
d = Derived()
print d.a
print d.b
And yes, this is the way in Python to call parent's method.
Yes, Python supports multiple inheritance.
class Base1(object):
def hello(self):
print "Base1: Hello"
class Base2(object):
def hello(self):
print "Base2: Hello"
class Derived(Base1, Base2):
pass
d = Derived()
d.hello() # this prints "Base1: Hello"
Why the above code calls Base1.hello?
This relates to MRO in Python.
In C++, we can use operator+ to overload the plus operator for a class.
In Python, operator overloading is implemented by special methods.
Remember? Special methods are the methods that both begins and ends with "__"(double underscores).
class Base(object):
def __init__(self, data):
self.data = data
def __add__(self, other):
return Base(self.data + other.data)
b1, b2 = Base(1), Base(2)
print b1 + b2
There are a lot of operators in Python you can overload.
You can check the full list here.
__add__( self, other)
__sub__( self, other)
__mul__( self, other)
__mod__( self, other)
__pow__( self, other[, modulo])
__and__( self, other)
__xor__( self, other)
__or__( self, other)
...
class DBTransaction(object):
def __init__(self, db_handle):
self.__db_handle = db_handle
def __enter__(self):
self.__transaction = db_handle.create_transaction()
self.__transaction.begin()
return self.__transaction
def __exit__(self, exc_type, exc_value, traceback):
if exc_type is not None:
self.__transaction.roll_back()
else:
self.__transaction.commit()
from __future__ import with_statement # write this line if you're using Python 2.5
with DBTransaction(db_handle) as transaction:
transaction.query("select * from tbl1")
# other DB queries
# Here __exit__ method will be called to end the transaction.
print "DB transaction is done."
As you can see, Context Manager is a powerful feature to write fault tolerant software.
Any question?
Enjoy programming in Python!