python面向对象
来源:互联网 发布:java项目如何导出war包 编辑:程序博客网 时间:2024/06/10 04:32
面向对象(oop):把对象作为程序的基本单元,一个对象包含了数据和操作数据的方法。
类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
1、创建类和对象---------------------------------------------------------
类使用class关键字创建。类的域和方法被列在一个缩进块中。
属于一个对象或类的变量被称作“域”。域有两种类型:类的变量和对象的变量。
self参数:类的方法与普通函数只有一个特别的区别--类的方法必须有一个额外的参数self,但是在调用这个类的方法时并不为该参数赋值,Python解释器自己会把实例变量传进去。self就指向创建的实例对象本身。
类与实例的创建语法:
#创建类:
#创建类中的方法:
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类型。
- python 面向对象
- python面向对象初步
- python面向对象
- Python面向对象详解
- python面向对象编程
- python面向对象
- python 面向对象
- python 面向对象编程
- python面向对象编程
- python面向对象编程
- python 面向对象笔记
- Python 面向对象编程
- Python面向对象编程
- python面向对象1
- Python面向对象详解
- Python 面向对象编程
- python面向对象1
- Python面向对象基础
- ListView的几种特殊属性
- 字符串的一些php操作
- makefile中 = := ?= +=的区别
- Java 运算符 详解
- MAC OS下修改XAMPP自带的Mysql登录密码
- python面向对象
- 砝码称重问题【dp】
- Android获取手机短信和通话记录及通讯录
- HDU 2121 无固定点的最小树形图
- ThinkPHP3.2.3结合jQuery插件jQuery-File-Upload实现多图上传
- 机器学习&数据挖掘:特征选择之 wrapper approach
- 【Quartz】Quartz存储与持久化-基于quartz.properties的配置
- 图像通道数
- Makefile中的build构建机制