Day-8: 面对对象编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day-8: 面对对象编程相关的知识,希望对你有一定的参考价值。

  面对过程的程序设计方法意在将函数分成子函数,再依次调用这些函数来解决问题。

  而面对对象的程序设计方法,来源于自然界,类是实例的抽象,实例是类的具体。自定义出来的对象是类,而所有的数据都可以看成是对象,因此解决问题的方法是靠对象自己处理消息和相互传递消息。使用时,首先考虑的是需要创建什么样的对象,对象中有怎么样的属性,要实现什么功能(成为方法)。

  面向对象的抽象程度比函数要高,因为一个class中既包含数据,又包含操作数据的方法。其中,数据封装、继承和多态是面向对象的三大特点。

  创建类时,class后面跟类名,()中是所继承的类,没有特别的父类就写object,类中定义的第一个方法是__init__(self,.....),这是通过类创建实例时传入一些内部参数所需要的初始方法,如下:

class Student(object):

    def __init__(self, name, score):
        self.name = name
        self.score = score
>>> bart = Student(Bart Simpson, 59)
>>> bart.name
Bart Simpson
>>> bart.score
59

  依据所需的属性和功能设计类中的变量和方法,由类加上特定的参数创建特定的实例,之后对于所需要查看和调用的函数全部由实例内部实现,外部无需知道内部的实现细节,只管使用就OK了,这就是所谓的数据封装。

  • 数据访问权限

  对于对象的属性尽量封装,保证对象的独立完整性。也就是说,对于属性的修改和调用靠类自己内部实现和处理,这对于面向对象编程是很有好处的。不仅可以保证外部代码无法随意修改对象内部的状态,同时,在方法中,也可以对参数做检查,避免传入无效的参数。

  以双下划綫开头__,表示私有属性,无法访问;单下划线_开头,表示按照常用规则,应该看成私有属性;而以双下划綫__开头和结尾,表示这是个特殊属性,可以直接访问。

  例如创建Student类时,其中的属性name和score应该设成私有属性,保证数据的安全;同时,在类中的方法,增加修改的方法,提供接口:

class Student(object):

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

    def print_score(self):
        print %s: %s % (self.__name, self.__score)

  def get_name(self):
    return self.__name

  def get_score(self):
    return self.__score

  def set_score(self, score):
    if 0<=score<=100:
      self.__score = score
    else:
      raise ValueError("bad score")
  • 继承和多态

  在面向对象编程中,定义一个变量时,可以选择从已有的类中继承。这样,已有的类成为父类,新创建的类成为子类。子类继承父类的所有属性,也可在子类中重新定义属性,将会替换掉继承自父类的该属性。

  多态是指当以父类为参数传入函数中时,继承该父类的所有子类都可以作为参数传入实现相应的功能。

  例如已有Animal类,以Animal作为父类,创建新的子类Dog,Cat,而以Animal类为参数的run_twice函数,对于Dog、Cat类同样有效。

class Animal(object):
    def run(self):
        print Animal is running...
class Dog(Animal):
    def run(self):
        print Dog is running...

class Cat(Animal):
    def run(self):
        print Cat is running...
def run_twice(animal):
    animal.run()
    animal.run()
>>> run_twice(Animal())
Animal is running...
Animal is running...
>>> run_twice(Dog())
Dog is running...
Dog is running...
>>> run_twice(Cat())
Cat is running...
Cat is running...

  而如果新增加了一个子类Tortoise,该函数同样可行。

class Tortoise(Animal):
    def run(self):
        print Tortoise is running slowly...
>>> run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...

  这就是著名的“开闭”原则:

  对扩展开放:允许新增Animal子类;

  对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

  • 获取对象信息

  使用type():type方法只允许传入单个参数,返回该参数的type类型,做type类型判断时,注意import types

>>> import types
>>> type(abc)==types.StringType
True
>>> type(uabc)==types.UnicodeType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType
True

  使用isinstance():isinstance方法允许传入两个参数,第一个是待判断对象,第二个是类型

>>> isinstance(a, str)
True
>>> isinstance(ua, unicode)
True
>>> isinstance(a, unicode)
False

或者判断是否是某些类型中的一种:

>>> isinstance(a, (str, unicode))
True
>>> isinstance(ua, (str, unicode))
True

  使用dir():dir方法是获得一个对象的所有属性和方法。

>>> dir(ABC)
[__add__, __class__, __contains__, __delattr__, __doc__, __eq__, __format__, __ge__, __getattribute__, __getitem__, __getnewargs__, __getslice__, __gt__, __hash__, __init__, __le__, __len__, __lt__, __mod__, __mul__, __ne__, __new__, __reduce__, __reduce_ex__, __repr__, __rmod__, __rmul__, __setattr__, __sizeof__, __str__, __subclasshook__, _formatter_field_name_split, _formatter_parser, capitalize, center, count, decode, encode, endswith, expandtabs, find, format, index, isalnum, isalpha, isdigit, islower, isspace, istitle, isupper, join, ljust, lower, lstrip, partition, replace, rfind, rindex, rjust, rpartition, rsplit, rstrip, split, splitlines, startswith, strip, swapcase, title, translate, upper, zfill]

  属性中以双下划线__开头和结尾的,是特殊属性,可在自己写的对象中添加该属性的方法,达到一定的效果。

>>> class MyObject(object):
...     def __len__(self):
...         return 100
...
>>> obj = MyObject()
>>> len(obj)
100

  另外,如果不知道某个属性是否属于该对象,可以进行如下操作:

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

getattr可以传入默认显示值:

>>> getattr(obj, ‘z‘, 404) # 获取属性‘z‘,如果不存在,返回默认值404
404

 

以上是关于Day-8: 面对对象编程的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——JS中的面向对象编程

VSCode自定义代码片段9——JS中的面向对象编程

Python 面对对象编程

Python-5 面对对象编程

面对对象编程

浅谈Perl的类包模块与面对对象编程