首页 > 技术文章 > (董付国)Python 学习笔记---Python面向对象程序设计(1)

erice-he 2019-09-01 19:17 原文

面向对象程序设计

  • 面向对象程序设计(Object Oriented Programming,OOP)主要针对大型软件设计而提出,使得软件设计更加灵活,能够很好地支持代码复用和设计复用,并且使得代码具有更好的可读性和可扩展性。
  • 面向对象程序设计的一条基本原则是计算机程序由多个能够起到子程序作用的单元或对象组合而成,这大大地降低了软件开发的难度,使得编程就像搭积木一样简单。
  • 面向对象程学设计的一个关键性观念是将数据以及对数据的操作封装在一起,组成一个相互依存、不可分割的整体,即对象。对于相同类型的对象进行分类、抽象后,得出的共同特征而形成了类,面向对象程序设计的关键就是如何合理地定义和组织这类以及类之间的关系
  • Python完全采用了面向对象程序设计的思想,是真正面向对象的高级动态编程语言,完全支持面向对象的基本功能,如封装、继承、多态以及对基类方法的覆盖或重写。
  • Python中对象的概念很广泛,Python中的一切内容都可以称为对象,除了数字、字符串、列表、元组、字典、集合、range对象zip对象等等,函数也是对象,类也是对象。
  • 创建类时用变量形式表示的对象属性称为数据成员,用函数形式表示的对象行为称为成员方法,成员属性和成员方法称为类的成员

6.1.1 类定义语法

  • Python使用class关键字来定义类,class关键字之后是一个空,然后是类的名字,再然后是一个冒号,最后换行并定义类的内部实现。
  • 类名的首字母一般要大写,当然也可以按照自己的习惯定义类名,但一般推荐参考惯例来命名,并在整个系统的设计和实现中保持风格一致,这一点对于团队合作尤其重要。
class Car:
    def infor(self):
        print("This is a car ")
  • 定义了类之后,可以用来实例化对象,并通过“对象名.成员”的方式来访问其中的数据成员或成员方法。
class Car:
    def infor(self):
        print("This is a car ")

car = Car()
car.infor()
This is a car 
  • 在Python中,可以使用内置方法**isinstance()**来测试一个对象是否为某个类的实例。
class Car:
    def infor(self):
        print("This is a car ")

car = Car()
car.infor()

print(isinstance(car,Car))
print(isinstance(car,str))
This is a car 
True
False
  • Python提供了一个关键字“pass”,类似于空语句,可以用在类和函数的定义中或者选择结构中。当暂时没有确定如何实现功能,或者为以后的软件升级预留空间,或者其他类型功能时,可以使用该关键字来“占位”。
>>> class A:
...     pass
...
>>> def demo():
...     pass
...
>>> if 5>3:
...     pass
...
>>>

6.1.2 self参数

  • 类的所有实例方法都必须至少有一个名为self的参数,并且必须是方法的第一个形参(如果有多个形参的话),self参数代表将来要创建的对象本身
  • 在类的实例方法中访问实例属性需要以self为前缀
  • 在外部通过对象名调用对象方法时并不需要传递这个参数
  • 如果在外部通过类名调用对象方法则需要显示为self参数传值。
  • 在Python中,在类定义实例方法时将第一个参数定义为“self”只是一个习惯,而实际上类的实例方法中第一个参数的名字是可以变化的,而不必须使用“self”这个名字,尽管如此,建议编写代码时仍以self作为方法的第一个参数名字。
>>> class A:
...     def __init__(hahaha,v):
...             hahaha.value = v
...     def show(hahaha):
...             print(hahaha.value)
...
>>> a = A(3)
>>> a.show()
3

6.1.3 类成员与实例成员

  • 属于实例的数据成员一般是指在构造函数__init__()中定义的,定义和使用时必须以self作为前缀;属于类的数据成员是在类中所有方法之外定义的。
  • 在主程序中(或类的外部),实例属性属于实例(对象),只能通过对象名访问;而类属性属于类,可以通过类名或对象名都可以访问。
  • 实例方法中可以调用该实例的其他方法,也可以访问类属性以及实例属性。
  • 在Python中比较特殊的是,可以动态地为类和对象增加成员,这一点是和很多面向对象程序设计语言不同的,也是Python动态类型特点的一种重要体现。
class Car:
    price = 10000                   #定义类属性
    def __init__(self,c):
        self.color = c              #定义实例属性

car1 = Car("Red")                   #实例化对象(car1就是self成员)
car2 = Car("Blue")
print(car1.color,Car.price)         #查看实例属性和类属性的值
Car.price = 11000                   #修改类属性
Car.name = 'QQ'                     #动态增加类属性
car1.color = "Yellow"               #修改实例属性
print(car2.color,Car.name,Car.price)
print(car1.color,Car.name,Car.price)

运行结果:

Red 10000
Blue QQ 11000
Yellow QQ 11000

如何把普通函数转化为成员方法:

import types

def setSpeed(self,s):
    self.speed = s

car1.setSpeed = types.M ethodType(setSpeed,car1)     #动态增加成员方法
car1.setSpeed(50)                                   #调用成员方法
print(car1.speed)
  • Python类型的动态性使得我们可以动态为自定义类及其对象增加新的属性和行为,俗称混入(mixn)机制,这在大型项目开发中会非常方便和实用。
  • 例如系统中的所有用户分类非常复杂,不同用户组具有不同的行为和权限,并且可能会经常改变。这时候我们可以独立地定义一些行为,然后根据需要来为不同的用户设置相应的行为能力。
>>> import types
>>> class Person(object):
...     def __init__(self,name):
...             assert isinstance(name,str),'name must be string'
...             self.name = name
...
>>> def sing(self):
...     print(self.name+'can sing.')
...
>>> def walk(self):
...     print(self.name+'can walk.')
...
>>> def eat(self):
...     print(self.name+'can eat.')
...
>>> zhang = Person('zhang')
>>> zhang.sing()                                #用户不具有该行为
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'sing'
>>> zhang.sing = types.MethodType(sing,zhang)   #动态增加一个新行为
>>> zhang.sing()
zhangcan sing.
>>> zhang.walk()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'walk'
>>> zhang.walk = types.MethodType(walk,zhang)   #动态增加一个新行为
>>> zhang.walk()
zhangcan walk.
>>> del zhang.walk                              #删除用户行为
>>> zhang.walk()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'walk'
>>>
  • 在Python中,函数和方法是有区别的。方法一般指与特定实例绑定的函数,通过对象调用方法时,对象本身被作为第一个参数隐式传递过去,普通函数并不具备这个特点。
>>> class Demo:
...     pass
...
>>> t = Demo()
>>> def test(self,v):
...     self.value = v
...
>>> t.test = test
>>> t.test                      #普通函数
<function test at 0x000001545CED43A8>
>>> t.test(t,3)                 #必须为self参数传值
>>> t.test = types.MethodType(test,t)
>>> t.test                      #绑定的方法
<bound method test of <__main__.Demo object at 0x000001545CED7188>>
>>> t.test(5)                   #不需要为self参数传值

推荐阅读