Python 5 面对对象编程
面向对象编程:
- 面向过程:根据业务逻辑从上到下写垒代码
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
封装
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
多态
1、封装:
实例变量,类变量: class a(object): name = 123321 #类变量 def __init__(self,name,age): self.name= name #实例变量 self.age =age b = a('cheng',22) print(b.name) 注:b.name先找实例变量里有没有,再看类变量有没有。 私有方法,私有属性: class a(object): name = 123321 __age = 24 #私有属性 def __init__(self,name,age): self.name= name self.__age =age def __ab(self): #私有方法 print(self.__age) b = a('cheng',22) print(b.__age)注:私有方法,属性只能在类里面调用,不能在外面调用。使用的时候用self.__属性或方法名。
2、继承
在多继承里,只继承一个构造函数,继承顺序为:
把下面代码用python2 和python3都执行一下
#_*_coding:utf-8_*_ class A: def __init__(self): self.n = 'A' class B(A): # def __init__(self): # self.n = 'B' pass class C(A): def __init__(self): self.n = 'C' class D(B,C): # def __init__(self): # self.n = 'D' pass obj = D() print(obj.n)
在Python2里:
经典类:深度优先
新式类:广度优先
在python3里:
经典类和新式类都是广度优先。
class People(object): def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) class Man(People): def __init__(self,name,age,eye): super(Man,self).__init__(name,age) #上面和下面是一样的 # People.__init__(self,name,age) self.eye = eye man1=Man('cheng',22,'blue') print(man1.name) 重构父类的方法后,再想调用父类的方法,用父类名.重构的方法名(self)
静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
class people(object): def __init__(self,name): self.name = name @staticmethod def eat(self): print("%s is eating ...."%self.name) a = people("xiao") a.eat()
上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
想让上面的代码可以正常工作有两种办法
1. 调用时主动传递实例本身给eat方法,即d.eat(a)
2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了
class people(object): def __init__(self,name): self.name = name @staticmethod def eat(): print(" is eating ....") a = people("xiao") a.eat()
类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class people(object): def __init__(self,name): self.name = name @classmethod def eat(self): print("%s is eating ...."%self.name) a = people("xiao") a.eat()
执行报错,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的
此时可以定义一个类变量,也叫name,看下执行效果
class people(object): name = "类变量" def __init__(self,name): self.name = name @classmethod def eat(self): print("%s is eating ...."%self.name) a = people("xiao") a.eat()
属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class people(object): name = "类变量" def __init__(self,name): self.name = name @property def eat(self): print("%s is eating ...."%self.name) a = people("xiao") a.eat()
调用会出错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了
正常调用如下
a = people("xiao") a.eat
类的特殊成员方法
1. __doc__ 表示类的描述信息
class Foo(object): """描述信息""" def __init__(self): self.name = 'alex' def func(self): print("is ok") #return 'func' obj = Foo() print(obj.__doc__)输出:描述信息
2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class C(object): def __init__(self): self.name = "name"
from lib.abc import C obj = C() print(obj.__module__) print(obj.__class__)输出:lib.abc<class 'lib.abc.C'>
3. __init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
5. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class a(object): def __init__(self): pass def __call__(self, *args, **kwargs): print(args[0]) obj = a() obj(1) 输出: 1
6. __dict__ 查看类或对象中的所有成员
class people(object): def __init__(self): self.name = "alex" self.age = 45 obj = people() print(obj.__dict__) 输出: {'name': 'alex', 'age': 45}
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class people(object): def __init__(self): self.name = "alex" self.age = 45 def __str__(self): return self.name obj = people() print(obj) 输出: alex
8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
反射
通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法
class Foo(object): def __init__(self): self.name = 'alex' def func(self): print("is ok") #return 'func' obj = Foo() #### 检查是否含有成员 #### print(hasattr(obj, 'name')) print(hasattr(obj, 'func')) #### 获取成员 #### print(getattr(obj, 'name')) getattr(obj, 'func')() #### 设置成员 #### setattr(obj, 'age', 18) setattr(obj, 'show', lambda num: num + 1) print(getattr(obj,"show")(1)) #### 删除成员 #### delattr(obj, 'name') delattr(obj, 'func')输出:TrueTruealexis ok2
动态导入模块
import importlib __import__('import_lib.metaclass') #这是解释器自己内部用的 #importlib.import_module('import_lib.metaclass') #与上面这句效果一样,官方建议用这个
Python 5 面对对象编程的更多相关文章
- 【我要学python】面对对象编程之继承和多态
class animal(object): def run(): print('animal is running...') class dog(animal): def run(self): pri ...
- python面对对象编程----2:__init__
面对对象编程估计我们最早接触到的就是__init__了,也就是实例的初始化处理过程: 1:来看看最基础的__init__ class Card(object): #抽象类Card,并不用于实例化 de ...
- Python学习6——再谈抽象(面对对象编程)
1.对象魔法 在面对对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法. 使用对象而非全局变量以及函数的原因有多个,而最重要的好处不过以下几点: 多态:可对不同类型的对象 ...
- 小学生绞尽脑汁也学不会的python(初识面对对象)
小学生绞尽脑汁也学不会的python(初识面对对象) 一. 面向对象思想 1. 面向过程. 重点在"过程". 按照实物的发展流程. 先干嘛,后干嘛, 最后干嘛.... 优点: 简单 ...
- python 的面相对象编程--对应c++
在python的面相对象编程中,我们常常在class中可以看到a(), _b() , __c(), __d()__这样的函数. 由于我是看廖雪峰老师的教程,廖老师为了简单起见,没有引入太多概念,我 ...
- 面对对象编程(OOP, Object Oriented Programming)及其三个基本特性
一千个读者,一千个哈姆雷特.对于面对对象编程,书上都会告诉我们它有三个基本特性,封装,继承,多态,但谈起对这三点的见解,又是仁者见仁智者见智,感觉还是得多去编程中体验把 . 面向对象编程(OOP, O ...
- C++ 基础语法 快速复习笔记---面对对象编程(2)
1.C++面对对象编程: a.定义: 类定义是以关键字 class 开头,后跟类的名称.类的主体是包含在一对花括号中.类定义后必须跟着一个分号或一个声明列表. 关键字 public 确定了类成员的访问 ...
- Day-8: 面对对象编程
面对过程的程序设计方法意在将函数分成子函数,再依次调用这些函数来解决问题. 而面对对象的程序设计方法,来源于自然界,类是实例的抽象,实例是类的具体.自定义出来的对象是类,而所有的数据都可以看成是对象, ...
- 跟着百度学PHP[4]OOP面对对象编程-7-OOP的一些关键子讲解
面对对象常用的一些关键子:http://www.cnblogs.com/xishaonian/p/6146794.html排版不是很好望见谅. THE END
随机推荐
- 简单使用shell 自动打包,发布项目 脚本
(1)打包,发布脚本 deploy.sh packagepath=/home/admin/testProject/project application=testProject mkdir -p $p ...
- mysql之replicate_do_table/replicate_ingore_table/replicate_wide_do_table/replicate_wide_ingore_table
参考:http://yhqlzz.blog.51cto.com/2557314/1159084/ mysql官网:http://dev.mysql.com/doc/refman/5.1/en/repl ...
- Tree UVA - 548 已知中序遍历和后序遍历,求这颗二叉树。
You are to determine the value of the leaf node in a given binary tree that is the terminal node of ...
- mysql 数据库复制表 create table city1 like city;
-- 只复制表结构 create table city1 like city; INSERT INTO test2 SELECT * FROM test; -- 上面的表必须存在 -- 复制整张表的数 ...
- neocomplcache 自动补全
key description ctrl+n 当前词补全项,下一个 ctrl+p 当前词补全项,上一个 :help NERDTree NERDTree帮助手册
- 回顾下WinMain
我们在学习标准C++的时候,都知道每个应用程序运行时都会先进入入口点函数main,而当从main函数跳出时程序就结束了.在Windows编程里面,也是一样的,只是我们的入口点函数不叫main,叫Win ...
- 第8章 Docker Compose 相关问题
8.1 你那个LNMP例子中的docker-compose.yml中有好多networks,都是什么意思啊? 我写的 LNMP 多容器互通的例子:https://coding.net/u/twang2 ...
- git push 推送大文件失败的处理办法
不小心把数据库备份文件放到git目录里了,导致无法上传代码. 首先参考了 这篇文章 http://www.cnblogs.com/qmmq/p/4604862.html. 按照文中一开始说的去做,可还 ...
- jetty 通过配置文件嵌入式启动web服务
定义 jetty.xml 启动文件 <?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty/ ...
- pycharm中格式标准化代码
点击之后,可以使代码标准化