Python面向对象编程(类和实例 访问限制 继承和多态 获取对象信息 实例属性和类属性)

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

数据封装、继承和多态是面向对象的三大特点

在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

类和实例

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

  1. 类可以起到模板的作用,因此,可以在创建实例的时候,通过定义一个特殊的_ init _方法,把一些我们认为必须绑定的属性强制填写进去。

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

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

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

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

  5. 封装的另一个好处是可以给类增加新的方法。

  6. 总结:
    类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
    方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
    和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同。

#常见的类
class Student(object):
    def __init__(self,name,score): #绑定属性
        self.name = name #外来参数赋值给self自己的参数
        self.score = score
    def print_score(self):
        print('%s: %s' % (self.name,self.score))
    def get_grade(self):
        if self.score >=90:
            return  'A'
        elif self.score >=60:
            return 'B'
        else: return 'C'
bart = Student('Bart Simpson', 59)
bart.print_score()
print(bart.get_grade())

访问限制

在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

外部要访问私有代码要用get方法;要修改的话就用set方法。在方法中,可以对参数做检查,避免传入无效的参数。

继承和多态

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。

  1. “开闭”原则:
    对扩展开放:允许新增父类的子类;
    对修改封闭:不需要修改依赖父类类型的固有方法等函数。

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

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

动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

获取对象信息

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?

  1. 使用type()函数:用来来判断对象类型,它返回对应的Class类型。

  2. 要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
  1. isinstance()可以一个对象是否是某种类型。isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。

  2. 父类的实例不是继承它的子类的类型。

  3. 能用type()判断的基本类型也可以用isinstance()判断,并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple:

>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True
  1. dir():
    获得一个对象的所有属性和方法,它返回一个包含字符串的list。

  2. 类似xxx的属性和方法在Python中都是有特殊用途的,比如len方法返回长度。

  3. getattr():getattr(obj, 'y') # 获取属性'y'

  4. setattr():setattr(obj, 'y', 19) # 设置一个属性'y'

  5. hasattr():hasattr(obj, 'x') # 有属性'x'吗?

  6. 如果试图获取不存在的属性,会抛出AttributeError的错误。

  7. 只有在不知道对象信息的时候,我们才会去获取对象信息。
    假设我们希望从文件流fp中读取图像,我们首先要判断该fp对象是否存在read方法,如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场。

def readImage(fp):
    if hasattr(fp, 'read'):
        return readData(fp)
    return None

实例属性和类属性

由于Python是动态语言,根据类创建的实例可以任意绑定属性。

在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。


学习网站:www.liaoxuefeng.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值