Python初级008-面向对象
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python初级008-面向对象相关的知识,希望对你有一定的参考价值。
面向对象
目录
1:类与对象
-------什么是类和对象
-------什么是属性与方法
2:面向对象的三大类型
-------封装
-------继承
-------多态
一、类与对象
-------什么是类和对象
Python中什么是对象?object=对象
Python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象。对象是存在的。
Python中什么是类?class=类
在python中,把具有相同属性和方法的对象归为一个类(class)
比如人类,动物,植物等等,这些都是类的概念。
我们在描述一个真实对象(物体)时包括两个方面:
它可以做什么(行为--动态)
它是什么样的(属性或特征---静态固有的)。
结论:
类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化。类不代表具体的事物,而对象表示具体的事物。也可以说类就是对象,对象=属性+方法。
-------什么是属性与方法
通过描述属性(特征)和行为来描述一个对象的。比如家里的小狗,它的颜色,大小,年龄,体重等是它的属性或特征。它会汪汪叫,会摇尾巴等是它的行为。在python中,一个对象的特征也称为属性(attribute)。它所具有的行为也称为方法(method
总结:实际上对象的属性就是定义的变量,方法就是定义的函数。
例子:简单的认识类,对象,属性和方法
>>> class people: #定义的一个类,类名为people
... def speak(self): #定义了speak函数,即为对象的方法
... print ("hello!")
>>> jack = people() #对象是类的实例,即创建了jack对象
>>> tom = people() #创建tom实例(对象)
>>> import tab #导入table键功能模块
>>> jack. #输入jack.(对象),可以看到以下方法
jack.__class__ j ack.__doc__ jack.__module__
Jack.speak jack.height jack.age
>>> jack.speak() #引用speak方法
hello!
>>> jack.age=39 #定义了变量,即对象的属性---->添加对象jack的属性,age=39
>>> jack.height=120 #添加height属性
例子:初始化对象
创建类时,可以先给方法定义定义一个特定的方法,语法是__init__(),括号中放的是定义对象特定的方法。,只要创建这个类的一个实例(对象),就会运行这个方法。可以向__init__()方法传递参数,这样创建对象时就可以把属性设置为你希望的值,__init__()这个方法会在创建对象时完成初始化。
>>> class peo:
... def __init__(self,name,age,sex):
... self.Name = name
... self.Age = age
... self.Sex = sex
... def speak(self):
... print "my name" + self.Name
例子:
>>> class Ball:
def setName(self,name):
self.name = name
def kick(self):
print("我叫%s,你好。" % self.name)
>>> a = Ball()
>>> a.setName(‘Genal‘)
>>> b = Ball()
>>> b.setName (‘Alix‘)
>>> a.kick()
我叫Genal,你好。
>>> b.kick()
我叫Alix,你好。
二、面向对象的三大特性
1、多态 : 可以对不同类的对象使用同样的操作(指就算不知道变量所引用的对象类型是什么,还是能对他进行操作,而它也会根据对象或类的类型的不同而表现出不同的行为)
2、封装 : 对外部事件对象工作的具体细节
3、继承 : 通用的类为基础建立专门的类对象
-------封装
1、将内容封装到某处:对象的变量封装给类的变量
class People: #定义一个People类
def __init__(self,name,age,sex): #构造方法,(当实例化对象时,自动执行这个方法)
self.name = name #指定对象的变量封装给类的变量
self.age = age
self.sex = sex
P1 = People(‘Alix‘,‘28‘,‘male‘) #实例化对象P1,将"allen"、25、"male"分别封装
到了 P1/self 中的name,age,sex属性中
P2 = People(‘Genal‘,‘15‘,‘man‘) #P2 ,同上
分析:
1:__init__ 属于python语言的构造函数,一个类只能有一个__init__方法当实例化对象时,自动执行这个方法
2:__init__中的self是一个形式参数,在所有定义的方法当中,括号()里面的参数第一个必须是self参数,当然,python语言中是自带的,可以不写。Self参数表示的是对象的自己,如上述的例子中,self所代表的对象就是P1和P2。
3:(self,name,age,sex)括号中的参数除了self外,都可以把他看做是变量(变量是对象的属性),
4:”域“的概念:属于一个对象或类的变量被称为域,其实就是类里面定义的变量
域——类的变量和对象的变量
1)类的变量:由一个类的所有对象(实例)共享使用((self,name,age,sex)中name,age,sex三个就是类的变量),只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。我理解为:其实它就是一个类的全局变量,类实例化后的对象都可以调用该变量。
2)对象的变量: 由类的每个对象/实例拥有((‘Alix‘,‘28‘,‘male‘)中的三个变量就是对象的变量,不能给其他对象使用)。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。我理解的是:不同的对象调用该变量,其值改变后互不影响。
3)变量的应用
属于类级别的变量,在使用它的时候一定要带上类型名字 比如 MyClass.count
属于每个对象级别的变量,在调用的时候一定要带上self表明属于当前对象。self.name
5:self.name = name,self.name 可以看做是自己的变量,是一个变量,名字叫做name,它是对象的变量(看上面的定义)。等于号后面的name也是一个变量,它是一个对类的变量(看上面的定义),这两个变量的名称虽然相同但是他们的域不同,所以代表不同的变量,区别就在于,第一个变量name的前面有个“点”。
6:在实例化对象P1和P2的过程中(封装),self分别等于P1和P2, 相对于内容被分别封装到了P1和P2中,每个对象都有name、age、sex属性。
封装过程如下
2、从某处调用被封装的内容:
例子:通过对象直接调用被封装的内容
class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
P1 = People(‘Alix‘,‘28‘,‘male‘)
P2 = People(‘‘Genal‘,‘15‘,‘man‘)
print P1.name #直接调用P1对象的name属性
print P2.name #直接调用P2对象的name属性
执行结果如下
Alix
Genal
---------继承
例子:多个子类继承父类
class Fruit:
def __init__(self,color):
self.color = color
print "fruit‘s color: %s" % self.color
def grow(self):
print "This is grow ..."
class Apple(Fruit): #继承了父类,Apple称为子类
def __init__(self, color): #显示调用父类的__init__方法
Fruit.__init__(self, color)
print "apple‘s color: %s" % self.color
class Banana(Fruit): #继承了父类
def __init__(self,color): #显示调用父类的__init__方法
Fruit.__init__(self,color)
print "banana‘s color:%s" % self.color
def grow(self): #覆盖了父类的grow方法
print "banana grow..."
apple = Apple(‘red‘)
apple.grow()
banana = Banana(‘yellow‘)
banana.grow()
执行结果如下:
======================= RESTART: C:/Python27/class.py =======================
fruit‘s color: red
apple‘s color: red
This is grow ...
fruit‘s color: yellow
banana‘s color:yellow
banana grow...
结果解析:
>>> apple = Apple(‘red‘)
fruit‘s color: red
apple‘s color: red
#定义了子类Apple的对象是apple。调用了子类Apple的方法,输出的是父类和子类,这就是继承-先输出父类在输出子类
>>> apple.grow()
This is grow ...
#apple是子类Apple的对象,这里调用的方法是父类的,输出的只有父类,没有子类。因为这里的子类Apple没有覆盖父类grow的方法。
>>> banana = Banana(‘yellow‘)
fruit‘s color: yellow
banana‘s color:yellow
#同上
>>> banana.grow()
banana grow...
#这里的banana是子类Banana的对象,覆盖了父类的grow方法,所以输出的直接是子类。
总结:
对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而以,不必一一实现每个方法。
////////////////////////////////////////////////////////////////////////////////////////////////////
那么问题又来了,多继承呢?
l 是否可以继承多个类
l 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?
1、Python的类可以继承多个类,Java和C#中则只能继承一个类
2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
例子:子类继承多个父类---经典类多继承
class D: #经典类
def bar1(self):
print "D.bar1"
class C(D): #子类C继承父类D
def bar1(self):
print "C.bar1"
class B(D): #子类B继承父类D
# def bar1(self):
# print "B.bar1"
pass #pass 代表什么也不做
class A(B,C): #子类A继承父类B和C
# def bar1(self):
# print "A.bar1"
pass #pass 代表什么也不做
op = A() #实例化对象op
op.bar1() #访问op中bar1方法,但是具体访问到哪个方法呢???
执行结果如下:
======================= RESTART: C:/Python27/class.py =======================
D.bar1
问题:为什么是访问到了D.bar1 ? ,
分析如下:
当我们实例化op,并且调用bar1方法时,由于在类中有多个bar1方法,因此对于经典类,它自己有一个查找顺序,A ---> B --> D --> C, python中查找的方法是从子类开始找,一层一层的往父类上找。首先找A,如果A中没有,则找B,如果B中没有,再找D,如果D中也没有,最后找C,如果都没有找到则报错;这种访问方式叫做深度优先.对于我们上面这个例子,由于找A 和 B 时都没有找到,则找到了D,因此打印了D.bar1,
例子:子类继承多种父类----新式类多继承
class D(object): #新式类
def bar1(self):
print "D.bar1"
class C(D):
def bar1(self):
print "C.bar1"
class B(D):
# def bar1(self):
# print "B.bar1"
pass #pass 代表什么也不做
class A(B,C):
# def bar1(self):
# print "A.bar1"
pass #pass 代表什么也不做
op = A() #实例化对象op
op.bar1() #访问op中bar1方法,但是具体访问到哪个方法呢???
执行结果如下
======================= RESTART: C:/Python27/class2.py =======================
C.bar1
问题:
为什么是C.bar1 ?? 和经典类结果相差很大...为什么?
分析如下:
新式类追寻的规律如下:A --> B --> D --> C,意思是,首先找A,如果A中没有,则找B,如果B中没有,则找C,如果C中也没有,则找D,最后都没找到,则报错;这种访问方式叫广度优先,对于我们上面的例子,由于A ,B 中都没有,则找C,C中找到了则打印C.bar1,
对于广度优先,你可以理解为找最近的点,比如上面的例子,A继承B,C ,由于在B中找不到,则去找C,(因为A继承C,离A最近,)找到C,则直接打印C.bar1
------------------多态
Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
以下是维基百科中对鸭子类型得论述:
在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,
一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的
集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”
可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
例子:Python “鸭子类型”
class F1:
pass
class S1(F1):
def show(self):
print ‘S1.show‘
class S2(F1):
def show(self):
print ‘S2.show‘
def Func(obj):
print obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
Python “鸭子类型”
以上就是本节对于面向对象初级知识的介绍,总结如下:
· 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
· 类 是一个模板,模板中包装了多个“函数”供使用
· 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
· 面向对象三大特性:封装、继承和多态
本文出自 “末班车” 博客,请务必保留此出处http://blxueyuan.blog.51cto.com/9673381/1877387
以上是关于Python初级008-面向对象的主要内容,如果未能解决你的问题,请参考以下文章