python 指南(07)面向对象编程

类和实例

一、面向对象和面向过程

  • 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行;为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度
  • 面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递

二、类和实例

  • 基本上来将python中的面向对象编程的实现和java中是很相似的

1、一个类的封装

  • 类名后面的object代表继承的类,这里的和java中的object是很相似的概念
  • init方法和java中的构造方法类似,就是用来初始化类的对象的,其中的参数self表示创建的实例本身和java中的this很类似
  • 值得注意的是python类中包括init方法在类的所有方法第一参数都是self,只是调用方法时不用传递这个参数,python解析器自动帮我们完成了
  • 和其他的脚本语言类似的是python也可以动态地为对象添加属性,这样就导致了对于同一个类的两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同
class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score


stu1 = Student('allen', 78)
stu1.haha = "test-haha"

print(stu1.name)
print(stu1.haha)

三、数据封装

  • 面向对象编程的一个重要特点就是数据封装
  • 方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据
  • 通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节,实现了数据和逻辑的封装
class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def get_grade(self):
        if self.score >= 90:
            return 'A'
        elif self.score >= 60:
            return 'B'
        else:
            return 'C'

访问限制

  • 访问的限制基本来讲和java差不多,就是把变量私有化,对外提供访问和修改的get和set方法
  • 但是有点不同的是,python并没有十分强硬的措施阻止你访问私有的数据,全靠自觉了

一、三种变量

  • __name__类似这样的特殊变量,特殊变量是可以直接访问的,不是private变量
  • 以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但按照约定还是把它视为private就好了
  • __name这样的变量是私有变量,直接访问会出错,需要提供get/set方法;但实际上直接访问也是能够实现,python对这种变量的私有化的实现是通过修改变量名来实现的,也就是说你实际看到的__name被解析器修改了名字,一般的解析器是把名字修改为这样的_Classname__name,但是最好不要这么做,不同的解析器的实现可能是不同的,而且约定了不要这么做的啦
class Student(object):
    def __init__(self, name, gender):
        self.name = name
        self.__gender = gender

    def get_gender(self):
        return self.__gender

    def set_gender(self,gender):
        self.__gender=gender

继承和多态

一、继承

  • 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写
  • 和iava不一样的是,java中一个方法接受一个父类参数,必须要求方法调用的时候传入的参数是这个父类或者其子类的对象;但是对于python这种动态语言,我不管你的继承关系是什么,只要你有相应的方法即可,这就是所谓的鸭子类型特点,只要看起来像并不一定要是,这也决定了python的继承不像静态语言那样是必须的

二、多态

  • 所谓的多态简单来说就是:我有一个方法,方法接受一个类型参数,调用方法的时候,你可以传递该类型的对象,也可以传递该类的子类对象,最终的效果是,不论是父类还是子类对象,方法都可以正常运行,并且因为传入对象的不同表现出不同的运行结果
  • 多态真正的威力在于:调用方只管调用,不管细节,而当我们新增一种子类时,只要确保相应方法编写正确,不用管原来的代码是如何调用的,这就是著名的开闭原则
    对扩展开放:允许新增子类
    对修改封闭:不需要修改依赖父类的函数

获取对象信息

一、使用type

  • type()函数返回对应的Class类型
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type(123)
False
  • 判断基本数据类型可以直接写int,str等,要判断一个对象是否是函数可以使用types模块中定义的常量
>>> 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

二、使用isinstance

  • isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上
  • 能用type()判断的基本类型也可以用isinstance()判断,总是优先使用isinstance()判断类型,可以将指定类型及其子类一网打尽
  • 还可以判断一个变量是否是某些类型中的一种:isinstance([1, 2, 3], (list, tuple))

三、使用dir

  • 如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list
  • 类似__xxx__的属性和方法在Python中都是有特殊用途的,比如python内置函数len(obj) 实际上是调用对象自己的__len__()函数来实现的
  • 通过getattr()、setattr()、hasattr()三个方法可以直接操作一个对象的状态(方法和属性)
setattr(obj, 'y', 19) # 设置一个属性'y'
hasattr(obj, 'y') # 有属性'y'吗?
getattr(obj, 'y') # 获取属性'y'
getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404

实例属性和类属性

  • 以下的代码中 name1 是类属性,name 是实例属性
  • 实例属性属于各个实例所有,互不干扰
  • 类属性属于类所有,所有实例共享一个属性
  • 不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误
class Student(object):
	name1 = 'Student'
    def __init__(self, name):
        self.name = name

发布了153 篇原创文章 · 获赞 51 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/stanwuc/article/details/103665154