廖雪峰Python教程学习笔记5-面向对象编程

来源:互联网 发布:数据机房建设标准 编辑:程序博客网 时间:2024/05/29 12:33

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。数据封装、继承和多态是面向对象的三大特点。

1 类和实例

类和实例的关系:
类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”。
e.g.

class Student(object):#类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。通常,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。    def __init__(self, name, score):#相当于C++里面的构造函数,self表示创建的实例本身,相当于C++里面的this指针        self.name = name        self.score = score

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

数据封装

进行数据封装的好处:

  • 隐藏函数实现的细节,调用容易
  • 可以给类增加新的方法

小结

  • 方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
  • 通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
  • 和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
>>> bart = Student('Bart Simpson', 59)>>> lisa = Student('Lisa Simpson', 87)>>> bart.age = 8>>> bart.age8>>> lisa.ageTraceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: 'Student' object has no attribute 'age'

2 访问限制

通过在属性的名称前加上两个下划线__,能让内部属性不被外部访问。在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

关于几种下划线变量名的比较:

  • 形如__xxx__:表示特殊变量,有特殊用途(如__name__表示函数的名字),可以直接访问,不是private变量;
  • 形如__xxx:表示私有变量,不能直接从外部访问;
  • 形如_xxx:外部可以访问,但按照约定俗成的规定,意为“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

总的来说,Python本身没有任何机制阻止你干坏事,一切全靠自觉。

3 继承和多态

e.g.

class Animal(object):#Animal是父类,继承object类    def run(self):        print 'Animal is running...'class Dog(Animal):#Dog是Animal的子类    def run(self):#定义自己的run()方法,覆盖父类的方法        print 'Dog is running...'class Cat(Animal):    def run(self):        print 'Cat is running...'def run_twice(val_name):        val_name.run()        val_name.run()>>>run_twice(Animal())Animal is running...Animal is running...>>> run_twice(Dog())Dog is running...Dog is running...

在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行。

继承的两个好处:

  • 子类可以继承父类的全部功能
  • 子类可以定义与父类同名的方法覆盖父类的方法,从而可实现多态

多态的好处:
调用方只管调用,不管细节,具有“开闭”原则:

  • 对扩展开放:允许新增Animal子类
  • 对修改封闭:不需要修改依赖Animal类型的run_twice()等函数

小结

  • 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写
  • 有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收

4 获取对象信息

使用type()判断对象类型

  • 基本类型都可以用type()判断
  • 如果一个变量指向函数或者类,也可以用type()判断
  • 还可以用types模块来判断某个对象的类型
>>> type(123)<type 'int'>>>> type('str')<type 'str'>>>> type(abs)<type 'builtin_function_or_method'>>>> type(a)<class '__main__.Animal'>>>> import types>>> type('abc')==types.StringTypeTrue

使用instance()判断对象类型

  • 判断基本类型
  • 判断类,判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上
  • 判断一个变量是否是某些类型中的一种
>>> isinstance('a', str)True>>> isinstance(u'a', unicode)True>>>d = Dog()>>> isinstance(d, Dog) and isinstance(d, Animal)True

使用dir()获得对象的所有属性和方法

dir()函数返回一个包含字符串的list

仅仅把属性和方法列出来是不够的,配合getattr()setattr()以及hasattr(),我们可以直接操作一个对象的状态

>>> setattr(obj, 'y', 19) # 设置一个属性'y'>>> hasattr(obj, 'y') # 有属性'y'吗?True>>> getattr(obj, 'y') # 获取属性'y'19>>> obj.y # 获取属性'y'19

小结

通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。

原创粉丝点击