“对象并不神秘,神秘的是你的眼睛。”
-------Elizabeth Bowen
“选取一个对象,对他进行修改,然后再进行一些其他的修改。”
-------Jasper Johns
概述
在面向对象之前,先看一下面向过程编程和函数式编程
面向过程编程
面向过程编程最容易被初学者接受,它往往使用一段长代码来实现指定功能,开发过程中最常见的就是复制粘贴。

1 # !/usr/bin/env python3 2 # hexm@2016/10/21 3 4 import getpass 5 6 ''' 7 输入用户名,如果用户名不在myInfo字典里,提示用户重新输入。 8 然后输入密码,连续输错三次密码,退出,并加入黑名单./pass.txt 9 当用户再次登录,提示账号被锁定。 10 ''' 11 myInfo = {"hexm": "xiaoming235", "alex": "alex3714"} 12 print("现有用户如下,输入用户名请输入以下用户:") 13 for name, pas in myInfo.items(): 14 print(' ',name,pas) 15 count = 0 16 # 被限制用户的列表 17 limitUser = [] 18 while True: 19 if count < 3: 20 # 捕获异常,第一次验证登录,pass.txt不存在 21 try: 22 limitUser = [x.strip(' ') for x in open('./pass.txt', 'r')] 23 except (FileNotFoundError): 24 pass 25 # 只第一次输入用户名 26 if count == 0: 27 username = input("Please input your username:") 28 29 # 如果用户名不存在,提示用户一直输用户名 30 while True: 31 if username not in myInfo.keys(): 32 print("no this user, reinput") 33 username = input("Please reinput your username:") 34 else: 35 break 36 # 如果是黑名单用户,break 37 if username in limitUser: 38 print("you account is locaked!!! Please contact xiaoming.unix@gmail.com") 39 break 40 if count == 0: 41 passwd = getpass.getpass("Please input your password:") 42 else: 43 passwd = getpass.getpass("Please reinput your password:") 44 45 # 验证 46 if username in myInfo.keys() and passwd == myInfo[username]: 47 print("验证通过,欢迎进入CMDB,经历一系列特殊服务,现在退出!") 48 break 49 else: 50 # 第三次输入,加入黑名单 51 if count == 2: 52 with open('./pass.txt', 'a') as f: 53 f.write(username) 54 f.write(' ') 55 print("password is wrong,locked your account.") 56 else: 57 break 58 count += 1
函数式编程
面向过程编程从上往下垒代码,但重用性太差,函数式编程可以增加代码重用性以及可读性。

1 #!/usr/bin/env python3 2 #hexm@2016/10/21 3 4 5 info = { 6 "上海":{ 7 "浦东新区": { 8 "张江": "51.com, 惠生公司,百度分部", 9 "唐镇": "2345公司,abc公司" 10 }, 11 "普陀区": "文华苑", 12 "闵行区": "刘德华" 13 }, 14 "北京": { 15 "昌平": { 16 "沙河": "老男孩公司" 17 } 18 } 19 } 20 21 def Page(info): 22 ''' 23 递归实现的三级菜单 24 ''' 25 m = 0 #m为选择的数字, 菜单有多少项选择,m会自增多少项 26 dict1 = {} 27 for x in sorted(info): 28 m = m + 1 29 print(m,x) 30 dict1[m] = x # x为每级菜单值, 并将数字对应地区存入临时字典中, 如:{1: '上海', 2: '北京'} 31 select = input("Please select a number:") 32 if select == 'q' or select == 'quit': 33 print("正在退出...") 34 exit(0) 35 select = int(select) 36 length = [ x for x in range(1, len(info) + 1) ] #菜单所有项的和, 如length = [1, 2] 37 if select in length: #选择的序号在length系列内 38 new = info[dict1[select]] # 下一级菜单值,如 info[dict1[1]]值为 {'普陀区': '文华苑', '浦东新区': {'唐镇': '2345公司,abc公司', '张江': '51.com, 惠生公司,百度分部'}} 39 if type(new) == dict: #如果类型为字典,递归 40 Page(new) 41 else: #否则输出,到最后一层 42 print(new) 43 else: 44 print("输入错误,退出..") 45 Page(info)
面向对象编程
在面向对象之前,先了解一下什么是对象,我们都知道,python中一切皆对象,所有的数据(包括整数,浮点数,布尔值,字符串,函数)都是以对象形式存在的,无论是简单的数据海山复杂的代码模块。
所有的python对象都拥有三个特性:身份,类型和值。
-
身份:对象的唯一标识符,通过id()得到
-
类型:对象有不同的类型,类型决定了可以对他进行的操作,比如一个类型为int的对象支持与另一个int对象相加,同时变量的类型还决定它里面的数据是可变的(变量)还是不可变的(常量)。可通过type()查看对象的类型。
-
值:对象表示的数据项。
面向对象编程是一种编程方式,此编程方式需要使用类和对象来实现,所以面向对象编程就是对类和对象的使用。
举个简单例子:
类比如说是一个生产青铜器的模具,而对象就是通过这个模具制作出来的。例如,python中的内置类string可以创建像‘cat’和‘duck’这样的字符串对象。
创建类和对象
- class是关键字,表示类
- 创建对象,类名称后加括号即可
面向对象 创建对象 通过对象执行方法
函数编程 执行函数
面向对象三大特性
一、封装
对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

1 # cat foo_class.py 2 #!/usr/bin/env python 3 # coding=utf-8 4 5 class c1(): 6 def __init__(self, name, obj): 7 self.name = name 8 self.obj = obj 9 class c2(): 10 def __init__(self, name, age): 11 self.name = name 12 self.age = age 13 def show(self): 14 print(self.name) 15 return 123 16 c2obj = c2('aa', 11) 17 # 将 'aa', 11 封装到对象c2obj,self里面的name,age属性中 18 c1obj = c1('hexm', c2obj) 19 # 将'hexm',c2obj对象封装到c1obj,self里面的name, obj属性中 20 print(c1obj.obj.age) 21 22 #c1 name = hexm 23 #c1obj.name 24 #c1obj.obj.age 25 #c1obj.obj.name 26 ret = c1obj.obj.show() 27 print(ret)
二、继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。
就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
如果继承了多个父类呢?也就是说多继承呢?
python2和python3中是不同的,python2分为两种:
- 深度优先
- 广度优先
python3只有一种:
- 广度度优先
python2中的新式类和python3按照广度优先方式查找
python2中的经典类按照深度优先方法查找
新式类:先去A类中找,没有去B类,B类中没有,去D类,D类中没有,去C类,C类中没有,去E类,E类中没有去F类。
经典类:先去A类中找,没有去B类,B类中没有,去D类,D类中没有,去F类,F类中没有,去C类,C类中没有,去E类
三、多态
多态简单来说就是多种类型,python函数中参数可以传任意类型的值,其他如iava、c中要指定int,float类型。
有缺点,比如阅读源码不知道是什么类型的。
什么时候使用面向对象合适
- 当某些函数具有相同参数时,可以使用面向对象方式,将参数值一次性封装到对象,以后去对象中取值即可,如数据库的增删改查及连接数据库主机名、用户名和密码。
- 需要创建多个事物,每个事物属性个数相同,但是值不通,如:贺晓明、朱晓静,都有姓名、年龄、血型,但都是不相同,即属性个数相同,值不同。
类和对象在内存中如何保存?
如上图所示,根据类创建对象时,对象中除了封装name和age的值外,还会保留一个类对象指针,该值指向当前对象的类,当通过obj1执行【方法一】时,过程如下:
- 根据当前对象中的 类对象指针 找到类中的方法
- 将对象obj1当做参数传给 方法的第一个参数self