java程序员的python之路(面向对象)

面向对象

什么是面向对象?和面向对象对应的就是面向过程,过程就是函数,面向过程考虑的是当前正在发生什么事情?主要表现就是定义了一个个的函数,通过函数的调用来组织程序。
而面向对象,考虑的是“谁”当前正在发生什么事情?“谁”就是对象。主要表现就是定义一个个的对象,通过对象之间的关系来组织程序。
说的比较笼统,不懂的还是不懂。python是一门面向对象的语言,面向对象有三个基本要素,继承,封装,多态。

对象

什么是对象?万物皆对象。人,山,空气等都是对象。但对象并不只包含万物,对象可以是抽象的,比如:思想。
现在我们拿鸟来简单的说一下。我们平时说到鸟的时候,其实就是泛指鸟类,是我们把一些飞禽抽象出来的一种概念。是一类动物
并不是单指一个,这就是面向对象中类的概念。而当我们说你看那只鸟好漂亮的时候,那只鸟就是特指某一只鸟,这只鸟就是对象。
我们把鸟的公共的特性和行为综合起来封装到一起就构成了鸟类。老鹰会飞,它生的孩子也会飞。鸵鸟会跑,它生的孩子也会跑。用一句话说“龙生龙,凤生凤,老鼠的孩子会打洞”,这叫做继承。上面我们简单地说了一下,类,对象以及封装和继承的概念,还有一个重要的概念就是多态,这个我们只能从程序中慢慢理解。

基本术语

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 实例变量(成员变量):定义在方法中的变量,只作用于当前实例的类。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

创建类和对象

定义类的格式如下:

 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_property

多态

python是弱类型的语言,多态的表现不是那么明显。多态的实现叫做动态绑定,也叫后期绑定,也就是说
直到运行的时候,才确定要执行的是哪个对象的方法。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

你可能感兴趣的:(python,python之路)