Python学习—面向对象学习上

面向对象简介

OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

面向对象的三大特性

Encapsulation 封装
把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
注意的是。这里说的属性并不仅仅是基本数据类型,还包括引用数据类型,也就是说,我们同样可以在一个类中封装其他类的对象,使其在这个类中实现引用类的相应办法。

Inheritance 继承
首先,什么叫继承呢?从理解上来说就是儿子获得了父亲所有的东西,并且这些东西是属于儿子的,儿子可以随意支配。那么从编程语言角度出发,就是一个类获取了另外一个类的全部方法,并且对这些方法进行自主的支配。在这里,被别人继承的类,我们叫父类,也叫超类或者基类。而继承了父类的类呢,就叫子类,也叫派生类。
所以一个类可以派生出子类,而子类会自动继承在这个父类里定义的属性、方法

Polymorphism 多态
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。

现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。就好像糖一样,有多种口味,你想吃什么口味的就可以吃什么口味。但在程序中,却不是你想要怎样就怎样。更多的是需要怎样去做就怎样去做。来一个算是比较官方的解释:在面向对象语言中,接口的多种不同的实现方式即为多态。

编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定

封装

1.类和对象

Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法。
对事物抽象出来类,即是封装。

Object 对象
一个对象即是一个类的实例化后的实例,即对象是类的实例。一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

python中使用class保留字来定义类,类名的首字母一定要大写。

以Student类为例,在Python中,定义类是通过class关键字:

class Student(object):
    pass

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

定义好了Student类,就可以根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class ‘__main__.Student‘>

可以看到,变量bart指向的就是一个Student的实例,后面的0x10a67a590是内存地址,每个object的地址都不一样,而Student本身则是一个类。

可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:

>>> bart.name = ‘Bart Simpson‘
>>> bart.name
‘Bart Simpson‘

由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:

class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score

注意:特殊方法“__init__”前后分别有两个下划线!!!

注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:

>>> bart = Student(‘Bart Simpson‘, 59)
>>> bart.name
‘Bart Simpson‘
>>> bart.score
59

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。
注意:self代表类的实例,而非类!

2.实例属性和类属性

属性有两种:实例属性、类属性。

实例属性是在构造函数init中定义的,定义时以self为前缀。
类属性是在类中方法之外定义的。
实例属性属于对象(实例),只能在实例化对象后通过对象名字访问。类属性属于类,可直接通过类名访问,不用实例化对象(尽管也可以通过对象来访问类属性,但不建议这样做,因为这样做会导致类属性值不一致)。类属性还可以在类定义之后,在程序中通过类名增加,如:类名.类属性=值

共有属性和私有属性

属性名以双下划线__开头的则是私有属性,否则是共有属性。私有属性在类外不能直接被访问。但python提供了访问私有属性的方式,可用于程序的测试和调试。方式如下:

对象名.__类名+私有属性名字

例如:

class People(object):
    def __init__(self,name,money):
        self.name = name
        self.__money = money

p1 = People(‘user1‘, 1000000)
p1.__People__money = 999999 #访问私有属性并修改~
print(p1.__People__money)

3.类的方法

类的方法:
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例对象。
self 的名字并不是规定不变的(因为是形参),也可以使用 this,但是最好还是按照约定是用 self。

公有方法和私有方法

公有方法、私有方法都属于对象,每个对象都有自己的公有方法、私有方法。公有方法通过对象名调用,私有方法则不能通过对象名调用,只能在属于该对象的方法中通过self来调用,即只能在类的内部调用 ,不能在类地外部调用。
两个下划线开头,声明该方法为私有方法。公有方法直接是写一个方法名即可。

类方法、静态方法

1.类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量

class Dog(object):
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)

d = Dog("hahaha")
d.eat()

执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的

Traceback (most recent call last):
  File "/Users/jieli/PycharmProjects/python_projects/面向对象/类方法.py", line 9, in <module>
    d.eat()
  File "/Users/jieli/PycharmProjects/python_projects/面向对象/类方法.py", line 6, in eat
    print("%s is eating" % self.name)
AttributeError: type object ‘Dog‘ has no attribute ‘name‘

此时可以定义一个类变量,也叫name,看下执行效果

class Dog(object):
    name = "hahahahahahaha"
    def __init__(self,name):
        self.name = name
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)

d = Dog("hahaha")
d.eat()

运行输出:
hahahahahahaha is eating

2.通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法。普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod #把eat方法变为静态方法
    def eat(self):
        print("%s is eating" % self.name)

d = Dog("hahaha")
d.eat()

上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

Traceback (most recent call last):
  File "/Users/jieli/PycharmProjects/python_projects/面向对象/静态方法.py", line 9, in <module>
    d.eat()
TypeError: eat() missing 1 required positional argument: ‘self‘

想让上面的代码可以正常工作有两种办法

1.调用时主动传递实例本身给eat方法,即d.eat(d)

class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod #把eat方法变为静态方法
    def eat(self):
        print("%s is eating" % self.name)

d = Dog("hahaha")
d.eat(d)

运行输出:
hahaha is eating

2.在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了

class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod
    def eat():
        print(" is eating")

d = Dog("hahaha")
d.eat()

运行输出:
 is eating

属性方法  

属性方法的作用就是通过@property把一个方法变成一个静态属性

class Dog(object):
    def __init__(self,name):
        self.name = name
    @property
    def eat(self):
        print(" %s is eating" %self.name)

d = Dog("hahaha")
d.eat()

调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了

Traceback (most recent call last):
 ChenRonghua is eating
  File "/Users/jieli/PycharmProjects/python_projects/面向对象/属性方法.py", line 8, in <module>
    d.eat()
TypeError: ‘NoneType‘ object is not callable

正常调用如下

d = Dog("hahaha")
d.eat

输出
 hahaha is eating

下一篇博客会涉及@property的详细情况,这里只作简介
另外可以参考博客:http://www.cnblogs.com/alex3714/articles/5213184.html

继承

1.单继承

顾名思义,单继承是指子类只继承一个父类。

#定义类
class People:
    #定义基本属性
    name = ‘‘
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))

#单继承
class Student(people):
    grade = ‘‘
    def __init__(self,n,a,w,g):
        #调用父类的构函
        People.__init__(self,n,a,w)
                #或者用super方法
                #super(People, self).__init__(n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

s = Student(‘ken‘,10,60,3)
s.speak()

2.多继承

子类同时继承多个父类


#类定义
class People:
    #定义基本属性
    name = ‘‘
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))

 #单继承
 class Student(people):
    grade = ‘‘
    def __init__(self,n,a,w,g):
        #调用父类的构函
        People.__init__(self,n,a,w)
        self.grade = g
    #覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

#另一个类,多重继承之前的准备
class Speaker():
    topic = ‘‘
    name = ‘‘
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))

#多继承
class Sample(Speaker,Student):
    a =‘‘
    def __init__(self,n,a,w,g,t):
        Student.__init__(self,n,a,w,g)
        Speaker.__init__(self,n,t)

test = Sample("Tim",25,80,4,"Python")
test.speak()   #方法名同,默认调用的是在括号中排前地父类的方法

经典类和新式类

      经典类的继承算法: 深度优先算法
      新式类的继承算法: 广度优先算法

python3全部都是新式类
在python2中既有新式类也有经典类

  • 在继承后,通过子类的对象调用某方法,如果子类没有, 则去父类找, 如果父类也没有, 就报错。
  • 私有属性、私有方法, 在类的内部都是可以访问的, 类的外部或者子类都不可以访问

多态

Pyhon 很多语法都是支持多态的,比如 len(),sorted()等, 你给len传字符串就返回字符串的长度,传列表就返回列表长度。

关于多态的讲解,廖雪峰老师的教程里讲的很容易理解,这里附上地址:继承和多态参考文章
另外附上老男孩Python3教程的面向对象讲解,因为他最后讲到了领域模型:传送门

最后关于多态,截取廖雪峰老师的一点讲解:
静态语言 vs 动态语言

对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:

原文地址:http://blog.51cto.com/13885935/2171920

时间: 2024-10-06 08:29:32

Python学习—面向对象学习上的相关文章

Python学习—面向对象学习下

面向对象下 1.构造方法与析构方法 class People(object): # 构造方法:__init__(),在实例化对象时自动执行的方法 def __init__(self, name, age): self.name = name self.age = age print("创建对象成功.......") # 析构函数:__del__(), 当你删除对象时,自动调用的方法 # 删除对象:del 对象名 def __del__(self): print("删除对象成功

Python 初识面向对象#学习猿地

> 面向对象编程——Object Oriented Programming,简称`OOP`,是一种**以对象为中心**的程序设计思想. > > 面向过程编程——Procedure Oriented Programming,简称`POP`,是一种**以过程为中心**的程序设计思想. ## 理解面向过程与面向对象思想 大家先思考一个问题:把大象装进冰箱,需要几步? 小品给出的答案:三步 第一步:打开冰箱门 第二步:把大象装进去 第三步:关上冰箱门 ##### 用面向过程去理解 > 上面

python Day6 面向对象学习

面向过程 VS 面向对象 编程范式 编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式. 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式. 两种最重要的编程范式分别是面向过

转 python语法学习面向对象之继承

传送门 python语法学习面向对象之继承 只要涉及到面向对象,”类“是必须出现的一个代名词. 类和对象是面向对象编程的两个主要方面.类创建一个新类型,而对象是这个类的实例. 类的一些概念: 包括初始化方法__init__,可以理解为构造,self,理解为this,等等在前一篇文章中介绍过,现在就学习类的继承. 继承: 面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制.继承完全可以理解成类之间的类型和子类型关系. 需要注意的地方:继承语法   class 派生类

Python 3学习 ——面向对象

Python 学习--面向对象 写此博客 是为了激励自己,并且将自己的心得以及遇到的问题与人分享 一.面向对象基础 面向对象就是一个类和对象的应用. 1.定义方法: ---------------------------------------------------------------- class 类名: def 方法名(self , arg): print(arg) 中间人 = 类名() 中间人.方法名(arg) ------------------------------------

Python 面向对象学习(一)

1. 面向对象的概念 面向对象编程--Object Oriented Programming,是我们在编程中解决问题的一个新的方式,一种编程的思想.而在常见的编程中,我们是以面向过程的方式解决的,首先我们了解一下面向对象与面向过程的基本概念. 1.1 面向过程 我们把完成一件工作的各个步骤依次编写代码,每一个步骤都可以封装成一个函数,在使用是只需要依次调用即可.特殊的,一个步骤也可以分成很多小的步骤,使用更小的函数来解决. 例如,把大象装进冰箱需要几步? 把冰箱门打开 把大象装进冰箱 把冰箱们关

Java学习总结(三)——面向对象(上)

Java学习总结(三) -面向对象(上) 一.面向对象的概念及思考方式 面向对象的理解:是一种编程思想,他将对象作为解决问题的基本元素,利用对象与对象之间的相互作用来设计程序. 2.面向对象的思考方式:(1)首先确定问题域中的对象 (2)确定对象的特征与功能 (3)了解对象与对象之间的关系 例:设计一个五子棋游戏的对象:·黑白双方对象     ·绘制棋盘     ·输赢规则 二.类与对象 1.对象:用来描述客观事物的一个实体,由一组属性和行为构成. 2.类:(1)是一个模板,他描述一类对象的行为

Python 2.7 学习笔记 面向对象的编程

python是一种面向对象的语言.本文介绍如何用python进行面向对象的编程. 首先我们说下对象和类,类是一种类型的定义,对象是类的实例. 一.内置对象类型(内置类) 其实我们前面已经大量用到了对象,如字符串.列表.字典等,这些对象的类型是python的内建对象类型. 比如: a=[] 这其实就是创建了一个空的列表对象,并将它赋值给变量a,变量a就指向了一个列表对象. 那列表对象对应的类是什么呢?其实列表对象对应的类名是list. 我们还可以通过类来创建对象,看下例子: >>> pri

Python自动化开发学习12-MariaDB

关系型数据库 主流的关系型数据库大概有下面这些: Oracle : 甲骨文公司的企业级的数据库 SQL Server : 微软的 MySQL : 免费的数据库,现在也属于Oracle的旗下产品 MariaDB : 开源的数据库,MySQL的一个分支 PostgreSQL : 也是开源的 SQLite : 一款轻量级的数据库 DB2 : IBM的 RDBMS 术语 RDBMS(Relational Database Management System)即关系数据库管理系统,在开始之前,先了解下RD