什么是面向对象?和面向对象对应的就是面向过程,过程就是函数,面向过程考虑的是当前正在发生什么事情?主要表现就是定义了一个个的函数,通过函数的调用来组织程序。 而面向对象,考虑的是“谁”当前正在发生什么事情?“谁”就是对象。主要表现就是定义一个个的对象,通过对象之间的关系来组织程序。 说的比较笼统,不懂的还是不懂。python是一门面向对象的语言,面向对象有三个基本要素,继承,封装,多态。
什么是对象?万物皆对象。人,山,空气等都是对象。但对象并不只包含万物,对象可以是抽象的,比如:思想。 现在我们拿鸟来简单的说一下。我们平时说到鸟的时候,其实就是泛指鸟类,是我们把一些飞禽抽象出来的一种概念。是一类动物 并不是单指一个,这就是面向对象中类的概念。而当我们说你看那只鸟好漂亮的时候,那只鸟就是特指某一只鸟,这只鸟就是对象。 我们把鸟的公共的特性和行为综合起来封装到一起就构成了鸟类。老鹰会飞,它生的孩子也会飞。鸵鸟会跑,它生的孩子也会跑。用一句话说“龙生龙,凤生凤,老鼠的孩子会打洞”,这叫做继承。上面我们简单地说了一下,类,对象以及封装和继承的概念,还有一个重要的概念就是多态,这个我们只能从程序中慢慢理解。
定义类的格式如下:
class ClassName: <特性> <行为>下面我们定义一个鸟类,并且让它有一个可以飞的方法(函数),如下:
class Bird: def fly(self): print("I fly")上面我们创建了一个鸟的类,并定义了一个fly方法(成员方法),此方法有一个参数self,表示当前对象的意思。那么我们怎么创建这个类的对象,并且让它飞呢?如下:
bird = Bird() bird.fly(输出结果:
I fly我们通过类名和一对括号来创建一个鸟类的对象,并把这个对象赋值给bird引用,然后使用bird引用调用鸟类的fly方法。
构造方法是用来创建对象使用的,可以让我们使用一些参数来实例化一个对象(创建一个对象),构造方法在创建对象的时候会自动执行。 现在我们要给我们的鸟类添加一个特性(成员变量)颜色,别想希望在创建 对象的时候指定颜色,那么我们就需要用到构造函数,构造函数的结构是固定的,如果父类和子类都重新定义了构造方法_init( )_, 在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用。如下:
def __init__(self): self.data = []下面我们重新编写鸟类,添加构造方法和成员变量,代码如下:
class Bird: #构造方法 def __init__(self,c): print("Bird init") #成员变量 self.color = c #成员方法 def fly(self): print("I can fly.") #成员方法 def getColor(self): print("I am %s color." % self.color) #创建对象,为构造函数传递参数red bird = Bird("red") #调用方法 bird.fly() #访问成员变量 print(bird.color)输出结果如下:
Bird init I can fly. red通过上面的代码,我们看到,我们可以使用对象引用加上“.”的方式访问对象的方法和属性。
继承的结构如下:
class ChildClass(BaseClassName1):现在我们需要一个鸵鸟的类,并希望它有一个奔跑速度的特性和奔跑的方法,让鸵鸟的类继承鸟类;
class Ostrich(Bird): #构造函数 def __init__(self,c,s): #调用父类Bird1的构造方法 #子类的构造方法必须调用父类的构造方法,且必须在构造方法的第一行。 Bird.__init__(self, c) #成员变量 self.runSpeed = s #成员方法 def run(self): print("I can run,speed is %i km/h" % self.runSpeed) ostrich = Ostrich("gray",100) ostrich.fly() ostrich.run() print(ostrich.color) print(ostrich.runSpeed)输出结果如下:
Bird init I can fly. I can run,speed is 100 km/h gray 100我们可以看到鸵鸟类的对象可以访问fly方法以及color属性,但是鸵鸟类中并没有color和fly方法,这是是从Bird类中继承来的。这里我们就看到了继承的强大之处。但是有个问题,我们都知道鸵鸟是不会飞的。那么我们需要重新实现一个Bird1的fly方法,这个过程我们称作重写。 代码如下:
class Ostrich(Bird): #构造函数 def __init__(self,c,s): #调用父类Bird1的构造方法 #子类的构造方法必须调用父类的构造方法,且必须在构造方法的第一行。 Bird.__init__(self, c) #成员变量 self.runSpeed = s #成员方法 def run(self): print("I can run,speed is %i km/h" % self.runSpeed) #重写父类fly方法 def fly(self): print("I can not fly")输出结果如下:
Bird init I can not fly I can run,speed is 100 km/h gray 100另外python中支持多继承,多重继承需要用逗号把父类分开。看下面代码:
class Animal: def howl(self): print("I can howl") def run(self): print("I can not run") #多重继承 class Chicken(Animal,Ostrich): def __init__(self,c,s): Ostrich.__init__(self, c,s) chiken = Chicken("green",10); chiken.fly() chiken.run() chiken.howl()输出结果如下:
Bird init I can not fly I can not run I can howl需要注意的是,如果多个类中有相同的方法,那么写在前面的父类会覆盖后面父类的方法。
上面的类中的属性和方法,在类外都可以通过点的方式来调用。为了保证封装性以及安全,某些属性和方法要禁止外部访问。python中双下划线开始的属性和方法是私有的,外部不能直接访问,如下例:
class Duck(Bird): def __init__(self,c,swi): Bird.__init__(self, c) self.__swim = swi def swimm(self): if self.__swim: print("I can swim") else: print("I can not swim") def __setSwim(self,swim): self.__swim = swim duck = Duck("write",True) duck.swimm() duck.__setSwim(False) print(duck.__swim)输出结果:
Bird init I can swim Traceback (most recent call last): File "E:\workspace-python\firstpython\src\first.py", line 36, in <module> duck.__setSwim(False) AttributeError: 'Duck' object has no attribute '__setSwim'报错,说明爽下划线开始的成员变量和成员方法,不能在外部访问。
类属性是直接写在类中的属性,此类的多个成员共享一份类属性,成员方法和类型发可以访问类属性,类方法和静态方法可以直接通过类名来访问,代码如下:
class Static: #类属性,多个实例对象共享此属性值 static_property = "static_property" def __init__(self,s): self.member_property = s #成员属性,对象独享此属性值 #静态方法,通过类型直接访问 @staticmethod def staticMethod(): print("staticMethod") #类方法,通过类型直接访问,可访问类属性 @classmethod def classMethod(cls): print(cls.static_property) #成员方法,通过对象访问 def memberMethod(self): print("memberMethod") static1 = Static("aaaaaa") static2 = Static("bbbbb") print(static1.member_property) print(static2.member_property) print(Static.static_property) Static.staticMethod() Static.classMethod()输出结果如下:
aaaaaa bbbbb static_property staticMethod static_propertypython是弱类型的语言,多态的表现不是那么明显。多态的实现叫做动态绑定,也叫后期绑定,也就是说 直到运行的时候,才确定要执行的是哪个对象的方法。python也是支持多态的, 多态的表现就是一个引用,在赋予不同的对象时表现出不同的行为。看下面的代码:
class Animal: def eat(self): print("I eat everything") class Fish(Animal): def eat(self): print("I eat water") class Sheep(Animal): def eat(self): print("I eat grasses") #定义函数,接收一个animal的参数 def eatWhat(animal): animal.eat() animal = Animal() fish = Fish() sheep = Sheep() eatWhat(animal) eatWhat(fish) eatWhat(sheep)输出结果为:
I eat everything I eat water I eat grasses