们大部分人的第一门编程语言是C,上课的时候老师告诉我们C是面向过程的语言。面向过程就是教计算机一步一步来,这种编程思维是我们比较容易接受的,或许这就是让我们入门学C的原因吧。
后面我们有学到了Java、C++,我们知道它是面向对象的,今天,我们来说说另一个面向对象的语言--python!
面向对象的语言有三个特性:封装、继承、多态!后面我们会一一介绍。
创建类和对象
面向对象编程方式有两个特别的东西,“类”和“对象”,类就是用来描述相同的属性和方法的对象的集合,用关键字class创建。而对象是通过类定义的数据结构。如下面这个例子,Test就是一个类;而对象包括类变量和实例变量以及方法,而t就是一个对象,它也是一个实例。
class Test:
def __init__(self):
print(self)
print(self.__class__)
t = Test()
#<__main__.Test object at 0x10a9fb3c8>
#<class '__main__.Test'>
我们在类中定义的第一个方法是__init__(),这是一个特殊的方法,被称为类的构造函数或初始化方法。当我们创建类的实例时,就会调用这个方法。其中这个self就是类的实例,我们通过打印可以看到,代表当前对象的地址,而self.__class__指向类。
需要注意的是类中的函数第一个参数必须是self,这个和特性之一的封装有关。
面向对象的三大特性
封装
封装,就是将内容封装到某个地方,后面再去调用被封装在某处的内容。
第一步,将内容封装到某处
class Test:
def __init__(self,name,age): #构造方法,它会在类创建对象时自动执行
self.name = name
self.age = age
t1 = Test('li',23) #将'li'和18分别封装到name、age属性中
t2 = Test('chen',28) #将'chen'和28分别封装到name、age属性中
第二步,在某处调用被封装的内容,调用封装的内容的方式有两种。
1、通过对象直接调用;
class Test:
def __init__(self,name,age):
self.name = name
self.age = age
t1 = Test('li',23)
print(t1.name)
print(t1.age)
t2 = Test('chen',28)
print(t2.name)
print(t2.age)
2、通过self间接调用
class Test:
def __init__(self,name,age):
self.name = name
self.age = age
def detail(self):
print(self.name)
print(self.age)
t1 = Test('li',23)
t1.detail()
t2 = Test('chen',28)
t2.detail()
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。
继承
继承即使“子承父业”!子类会继承父类的方法,而且python支持对继承,这点和C++一样;而Java是单继承的。
class Animal():
def __init__(self,name,breed):
self.name = name
self.breed = breed
def eat(self):
print("%s eat" %self.name)
def play(self):
print("%s playing"%self.name)
class cat(Animal):
def cry(self):
print("********")
class dog(Animal):
def cry(self):
print("========")
c1 = cat('kitty','cat')
c1.cry()
c1.eat()
c1.play()
c2 =cat('shit','cat')
c2.cry()
c2.eat()
c2.play()
#output:
#********
#kitty eat
#kitty playing
#********
#shit eat
#shit playing
#========
#jack eat
#jack playing
可以看到eat和play都被子类继承了,有了继承,可以减少重复代码的编写,当某几个对象有相同的特性的时候,就可以在父类中实现这些属性和方法,子类继承就好。
我们python是支持多继承的。
class A:
def bar(self):
print('a.bar')
class B(A):
pass
class C:
def bar(self):
print('c.bar')
class D(B,C):
pass
#def bar(self):
# print('d.bar')
b = B()
b.bar()
d = D()
d.bar()
c = C()
c.bar()
#a.bar
#a.bar
#c.bar
注意上例,我们的C输出符合我们的预期,就是如果子函数实现了父类的方法,那么子类的方法就会把父类的方法覆盖,我们把这个重写函数的操作叫做重写;然后函数b的输出也是符合我们的预期,就是子类没有重写父类的方法,那么子类实例就会调用父类的方法;但是为什么D这样输出呢?我们把这种继承叫做经典继承,在多继承的时候,它是按照深度优先查找的,那么查找的顺序就是D->B->A->C。这样就可以解释了。
多态
我们介绍过多态,python是一门动态类型的语言,它原生多态,所以就不介绍了,可以在相关文章找到。
属性与方法
属性和方法都是分为私有和公有,而且它们私有属性都是以“__”(注意,这是两个_)开头。
class test:
publincA = 0 #公有属性
_protectB = 10 # 受保护属性
__privateC = 5 #私有属性
def count(self):
self.publincA += 1
self._protectB += 1
self.__privateC += 1
print(self.__privateC)
def get__privateC(self):
return self.__privateC
t = test()
t.count()
print(t.publincA)
print(t._protectB)
#print(t.__privateA) #报错,实例不能访问私有属性
print(t.get__privateC())
print(t._test__privateC)
私有属性不能在类的外部被使用或者直接访问。注意到上面的_protectB属性是单划线的,这类属性是让我们最好不要去直接访问它;而对于双划线的属性,我们不能直接去访问它,这样会报错,但是我们可以通过对象._类__属性名以及类中定义的方法来访问它。
方法和属性也是差不多的,只是访问私有的方式少了一种而已。
class test:
def printA(self):
print("A")
def _printB(self):
print("B")
def __printC(self):
print("C")
t = test()
t.printA()
t._printB()
t._test__printC()
#t.__printC() #报错,不能直接访问私有方法
严格意义来说,python没有什么绝对私有的属性和方法,当初双划线的属性和方法是为了继承而存在,防止子类方法和属性覆盖父类的方法。
class test:
def printA(self):
print("A")
def _printB(self):
print("B")
def __printC(self):
print("C")
class testA(test):
def printA(self):
print("AA")
def _printB(self):
print("BB")
def __printC(self):
print("CC")
t = testA()
t.printA()
t._printB()
t._test__printC()
#t.__printC() #报错,不能直接访问私有方法
##output AA BB C
http://www.cnblogs.com/wupeiqi/p/4766801.html