python面向对象

来源:互联网 发布:java项目如何导出war包 编辑:程序博客网 时间:2024/06/10 04:32

面向对象(oop)把对象作为程序的基本单元,一个对象包含了数据和操作数据的方法。

类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。



1、创建类和对象---------------------------------------------------------

类使用class关键字创建。类的域和方法被列在一个缩进块中。

属于一个对象或类的变量被称作“域”。域有两种类型:类的变量和对象的变量。

self参数:类的方法与普通函数只有一个特别的区别--类的方法必须有一个额外的参数self,但是在调用这个类的方法时并不为该参数赋值,Python解释器自己会把实例变量传进去。self就指向创建的实例对象本身。

类与实例的创建语法:

#创建类:

class Foo:
#创建类中的方法:
    def Bar (self):    #self是特殊参数,必填
         #do something

#根据类Foo创建实例对象obj

obj = Foo()

eg:
# -*- coding: cp936 -*-class Foo:    def Hello(self,name):        print "Hello %s"%namename=raw_input("请输入您的姓名:")obj=Foo()obj.Hello(name)        #调用类的方法


2、构造函数与析构函数-----------------------------------------------------

构造函数:在建立一个对象时系统自动调用,用于某些初始化的工作(如对数据赋初值)。

析构函数:当一个类的对象离开作用域时,析构函数将被调用(系统自动调用)。析构函数的作用是完成一个清理工作(如释放从堆中分配的内存)。

__init__()     构造函数

__del__()     析构函数

一个类可以有多个构造函数,但只能有一个析构函数。对象被析构的顺序与建立时的顺序相反,即后构造的对象先析构。

构造函数:

有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数。

class Foo:
    def __init__(self,name):   #构造函数   
        self.name=name          #name为属性
        def Bar (self):               #类的方法
            #do something         

#在创建实例的时候,就把name属性绑定上去
#在创建一个对象的时候会自动调用构造函数
obj1= Foo('小B')  

obj1.name               #访问对象的name属性

>>>

'小B'


#也可以自由的给一个对象实例绑定属性

eg:

# -*- coding: cp936 -*-class Foo:    passobj3=Foo()obj3.name='小A'print obj3.name

Python允许对实例变量绑定任何数据,也就是说,对于同一个类的不同实例变量,它们可以拥有不同名称的变量:

eg:

# -*- coding: cp936 -*-class Foo:    def Bar (self):        passobj3=Foo()obj4=Foo()obj3.name='小C'obj4.age='18岁'print "%s\n%s\n"%(obj3.name,obj4.age)print "%s\n%s\n"%(obj3.age,obj4.name)

#此时obj3只有name这个实例变量,而obj4也只有age这个实例变量...

析构函数:

eg:

# -*- coding: cp936 -*-class Foo:    def __init__(self,name):        self.name=name    def __del__ (self):     #析构函数        print '删除了 %s'%self.name      obj1= Foo('小B')         obj2= Foo('小A')print obj1.namedel obj1 #自动调用析构函数del obj2print obj1.name

因为obj1已经被析构了,所以此时显示obj1没有定义。


3、类的属性与对象(实例)的属性-----------------------------------------------------

类的属性:由一个类的所有对象共享使用。当某个对象对类的属性做了改动的时候,这个改动会反映到其他的实例上。

对象的属性:由类的每个对象独自拥有。不对其他实例对象共享的。在同一个类的不同对象中,虽然对象的属性名相同,但是是互不相关的。

eg:

# -*- coding: cp936 -*-class Foo:    count=0                  #类的属性  归类Foo所有    def __init__(self,name):         self.name=name       #name为对象的属性        Foo.count+=1         #每次创建对象count值都会加1    def add_count(self,n):        Foo.count=nobj1 = Foo('小B')   obj2 = Foo('小A')             #创建实例obj1和obj2print obj1.name,obj2.name     #打印实例obj1和obj2的name属性print obj1.count         #因为类的属性对类的所有实例都共享使用的,所以可以通过实例访问类的属性print Foo.count          #也可以直接通过类访问类的属性obj1.add_count(8)        #通过实例obj1修改类的属性count的值print obj1.count,obj2.count  #因为类的属性是类所有实例共享的,所以obj1改变了count的值也反映到obj2上obj1.count=666           #给实例obj1绑定count属性print obj1.count,obj2.count,Foo.count #因为obj1有了自己的count属性,因为会优先使用自己的。                  #而obj2没有count属性,因此还是享有类的count属性,而类本身也是访问自身的属性del obj1.count    #删除对象obj1的count属性print obj1.count  #因为上条语句已经将obj1的count属性删除了,所以obj1访问的是类的count属性


访问限制:

类的私有属性(变量):把属性名称前加上两个下划线__,即为类的私有属性。类的私有属性只有内部可以访问,外部不能访问。

如:

定义普通属性时:

# -*- coding: cp936 -*-class Student:    def __init__(self,name):        self.name=name    def addScore(self,score):        self.score=scorestu=Student('小A')stu.addScore(80)print stu.name,stu.score


定义为私有属性时:无法从外部访问 stu.__name和stu.__score了。

# -*- coding: cp936 -*-class Student:    def __init__(self,name,score):        self.__name=name        self.__score=score    def print_(self):        print self.__name,self.__scorestu=Student('小A',80)stu.print_()print stu.__score,stu.__name

另外:

# -*- coding: cp936 -*-class Student:    def __init__(self,name,score):        self.__name=name        self.__score=score    def print_(self):        print self.__name,self.__score        stu=Student('小A',80)stu.score=86stu.name='大A'stu.print_()print stu.score,stu.nameprint stu.__score,stu.__name,


因为

stu.score=86
stu.name='大A'   是又构建了两个普通属性,所以在外部可以正常引用stu.score,stu.name,输出结果print stu.score,stu.name。


stu=Student('小A')
stu.addScore(88)  是构建了两个私有属性,所以在外部不能正常引用stu.__score,stu.__name,内部通过print_()函数进行了引用。


set与get方法:

get方法:如果外部需要获取私有属性,可以使用get方法:

如:

# -*- coding: cp936 -*-class Student:    def __init__(self,name,score):        self.__name=name        self.__score=score    def get_name(self):        return self.__name    def get_score(self):        return self.__score        stu=Student('小A',80)name=stu.get_name()score=stu.get_score()print name,score

set方法:如果外部需要修改私有属性,可以使用set方法:

如:

# -*- coding: cp936 -*-class Student:    def __init__(self,name,score):        self.__name=name        self.__score=score    def set_name(self,name):        self.__name=name    def set_score(self,score):        self.__score=score    def print_(self):        print self.__name,self.__score        stu=Student('小A',80)stu.set_name('大A')stu.set_score(86)stu.print_()


类的私有方法:把方法名称前加上两个下划线__,即为类的私有方法。类的私有方法只有内部可以访问,外部不能访问。

如:

定义为普通方法:

# -*- coding: cp936 -*-class Student:    def add_Name_Score(self,name,score):        self.name=name        self.score=score    def print_Name_Score(self):        print self.name,self.score    def printAll(self):        self.print_Name_Score()        stu=Student()stu.add_Name_Score('小A',88)stu.print_Name_Score()stu.printAll()


定义为私有方法:无法从外部访问stu.__print_Name_Score(),但可以通过stu.printAll()方法内部访问__print_Name_Score()方法。
# -*- coding: cp936 -*-class Student:    def add_Name_Score(self,name,score):        self.name=name        self.score=score    def __print_Name_Score(self):        print self.name,self.score    def printAll(self):        self.__print_Name_Score()        stu=Student()stu.add_Name_Score('小A',88)stu.printAll()stu.__print_Name_Score()


4、继承多态---------------------------------------------

继承:当我们定义一个新的类时,当我们所需要的属性和方法某个现有的类已经具有了,那么可以继承这个现有的类。此时我们新定义的类称为子类,被继承的类称为父类、基类或者超类。子类可以引用被继承的类的全部属性和方法。子类也可以添加自己的属性和方法。

# -*- coding: cp936 -*-class Aminal:    def run(self,name):        print "The %s is running"%nameclass Dog(Aminal):    def eat(self,name,food):        print "The %s eat a %s"%(name,food)class Cat(Aminal):    def play(self,name,toy):        print "The %s is playing %s"%(name,toy)aminal=Aminal()dog=Dog()cat=Cat()aminal.run('cat and dog')dog.run('dog')dog.eat('dog','Hotdog')cat.run('cat')cat.play('cat',' wool ball')


说明:可以看到Dog类和Cat类本身是没有run()方法的,但是它们都继承了父类Aminal的run()方法,因此Dog类和Cat类的对象都可以引用run()方法,而Dog类也有自己的eat()方法,Cat类也有自己的play()方法。


多态:一个对象不仅仅可以以本身的类型存在,也可以作为其父类类型存在。一个基类(父类)的引用类型变量可以指向多种派生类(子类)对象。即:父类类型可以指向多种子类实例。

多态的两种形式:重载(overload)、覆盖(override)

重载(overload):同一个方法名匹配不同的参数。

如:

# -*- coding: cp936 -*-class Aminal:    def run(self,name):        print "The %s is running"%nameclass Cat(Aminal):    def play(self,name="",toy=""):        if name=="" and toy=="":            print "there are no aminals~"        elif toy=="":            print "The %s is playing"%name        else:            print "The %s is playing %s"%(name,toy)#main        cat=Cat()cat.play("Cat")cat.play("cat","wool ball")

说明:以上类似于play(self,name="",toy="")这样的带缺省值的方法,分别代表play(self)、play(self,name)、play(self,name,toy)等不同个参数的重载函数。


覆盖(override):父类与子类具有同名同参的方法,在子类继承父类时,继承下来的父类的同名同参的方法会被子类的覆盖掉。(通过父类类名.父类方法())

如:

# -*- coding: cp936 -*-class Aminal:    def run(self):        print "Aminal is running"    def who_run(self,aminal):        aminal.run()class Dog(Aminal):    def run(self):        print "Dog is running"class Cat(Aminal):    def run(self):        print "Cat is running"def aminal_run(aminal):    aminal.run()    #main        aminal=Aminal()        aminal.who_run(Aminal())aminal.who_run(Dog())aminal.who_run(Cat())print "------------------"aminal_run(Aminal())aminal_run(Dog())

说明:父类和子类都共同拥有run()方法,当子类调用run()方法的时候,父类的run()方法被子类自身的run()方法覆盖了,因此子类调用的是自己定义的run()方法。如以上aminal.who_run(Dog()),首先父类对象调用自身的who_run(self,aminal)方法,并传入子类对象Dog()作为参数即who_run(Dog()),在who_run(self,aminal)方法内部,通过传过去的参数aminal(Dog())对象调用了run()方法,因为此时的参数值是Dog()对象,所以,调用的run()方法是子类Dog的run()方法,父类Aminal的run()方法被覆盖掉了。


获取对象的信息:type()和isinstance()

type():获得对象的类型(也可以应用于基本数据类型)

使用:type(value)    value为要判断类型的内容

# -*- coding: cp936 -*-class Aminal:    def __init__(self):        print "There is an aminal~"#main        aminal=Aminal()print type(aminal),'\n',type('hahaha...')

这里通过type(aminal)得知aminal是一个instance实例对象类型。通过type('hahaha...')得知‘hahaha...’是一个str字符串类型。

isinstance():判断某一个对象是否是某个类型

使用:isinstance(obj,class)   obj为对象名  class为类名

# -*- coding: cp936 -*-class Aminal:    def __init__(self):        print "There is an aminal~"class Dog(Aminal):    def __init__(self):        print "There is a dog~"class Ross:    def __init__(self):        print "would you marry me?..."#main        dog=Dog()ross=Ross()print isinstance(dog,Aminal),"\n",isinstance(dog,Dog),"\n",isinstance(ross,Aminal)

说明:Dog类继承自Aminal类,因此,对象dog既是Aminal类型又是Dog类型。而ross对象没有继承Aminal类型,因此不是Aminal类型。


0 0
原创粉丝点击