1、简单例子
总体来讲,python的类和C++的类,思想上是一样的。只是语法会有略微的差别,所以这里主要关注语法。先上个简单例子:
class base (object):
static_v = 100
def __init__(self):
self.x = 0
self.y = 0
self.z = 0
print 'aaa', self.x, self.y, self.z
def pr(self):
print self.x, self.y, self.z
class child(base):
def __init__(self):
base.__init__(self)
self.a = 1
self.b = 1
self.c = 1
print 'bbb', self.x, self.y, self.z, self.a, self.b, self.c
def pr(self):
print self.x, self.y, self.z, self.a, self.b, self.c
通过这里个例子,python的基本类语法应该都包括了,大部分的思想和C++很像。
不过有一点需要强调的是__init__函数,在C++中,子类的构造函数是会调用父类的构造函数,这个是自动调用的,不需要显式调用。但是在python内不是,重写了子类__init__,父类__init__就不会被调用,如果想调用,需要像例子中那样。
2、类方法和静态方法
class Test:
@staticmethod
def sm():
print "static method is called..."
@classmethod
def cm(cls):
print "class method is called...", cls.__name__
Test.sm()
Test.cm()
看起来,类方法和静态方法貌似是一样的,因为其都是专属于类的(当然,可以通过实例来调用,但是我觉得python这样搞,把类和实例完全搞混了,所以我就理解成类方法和静态方法是专属于类的),两者的最大区别就是,类方法需要传递参数cls,这样一来,类的属性在类方法是可以随意调用的。
3、会用到的一些类属性
print Test.__doc__
print Test.__bases__
print Test.__name__
print Test.__module__
4、类和实例的内建函数
issubclass(sub, sup):判断父子类关系函数
isinstance(实例, 类):判断是否是某一类实例,可以判断内建类型(int、float等)
hasattr(), getattr(),setattr(), delattr():hasattr()函数是Boolean 型的,它的目的就是为了决定一个对象是否有一个特定的属性,一般用于访问某属性前先作一下检查。getattr()和setattr()函数相应地取得和赋值给对象的属性,getattr()会在你试图读取一个不存在的属性时,引发AttributeError 异常,除非给出那个可选的默认参数。setattr()将要么加入一个新的属性,要么取代一个已存在的属性。而delattr()函数会从一个对象中删除属性。
>>> class myClass(object):
... def __init__(self):
... self.foo = 100
...
>>> myInst = myClass()
>>> hasattr(myInst, 'foo')
True
>>> getattr(myInst, 'foo')
100
>>> hasattr(myInst, 'bar') False
>>> getattr(myInst, 'bar') Traceback (most recent call last):
File "<stdin>", line 1, in ?
getattr(myInst, 'bar')
AttributeError: myClass instance has no attribute 'bar'
>>> getattr(c, 'bar', 'oops!')
'oops!'
>>> setattr(myInst, 'bar', 'my attr')
>>> dir(myInst)
['__doc__', '__module__', 'bar', 'foo']
>>> getattr(myInst, 'bar') # same as myInst.bar #等同于 myInst.bar
'my attr'
>>> delattr(myInst, 'foo')
>>> dir(myInst)
['__doc__', '__module__', 'bar']
>>> hasattr(myInst, 'foo')
False
super(type, obj):给出当前类的父类对象,如super(MyClass,self).__init__(),这样就不用显式的给出父类。
如果obj 是一个实例,isinstance(obj,type)就必须返回True,
如果obj 是一个类或类型,issubclass(obj,type)就必须返回True
vars():方法和dict类似
class Test(object):
def __init__(self):
self.a = 0
self.b = 0
t = Test()
print dir(t)
print t.__dict__
print vars(t)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b']
{'a': 0, 'b': 0}
{'a': 0, 'b': 0}
总结:获取一个实例或类的属性的方法有,__dict__、vars()、dir(),前两种基本一样,而且返回的是字典,后一种返回的列表,dir要比前面两种返回的内容多一些python自动添加的属性,如果仅仅为了获取自定义的属性,用前两种就ok啦。
5、用特殊方法定制类
一个重载__str__(用于print)和加号的类
class Time60(object):
'Time60 - track hours and minutes'
def __init__(self, hr, min):
'Time60 constructor - takes hours and minutes'
self.hr = hr
self.min = min
def __str__(self):
'Time60 - string representation'
return '%d:%d' % (self.hr, self.min)
__repr__ = __str__
def __add__(self, other):
'Time60 - overloading the addition operator'
return self.__class__(self.hr + other.hr,
self.min + other.min)
def __iadd__(self, other):
'Time60 - overloading in-place addition'
self.hr += other.hr
self.min += other.min
return self
一个重载迭代器next的例子:
class AnyIter(object):
def __init__(self, data, safe=False):
self.safe = safe
self.iter = iter(data)
def __iter__(self):
return self
def next(self, howmany=1):
retval = []
for eachItem in range(howmany):
try:
retval.append(self.iter.next())
except StopIteration:
if self.safe:
break
else:
raise
return retval
a = AnyIter(range(10))
i = iter(a)
for j in range(1, 5):
print j, ':', i.next(j)