Python学习(十二) —— 面向对象
一、初识面向对象
面向过程的核心是过程,流水线思维,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点:极大地降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点:一套流水线或流程就是用来解决一个问题,代码牵一发而动全身。
面向对象的程序设计的核心是对象,上帝式思维,要理解何为对象。
优点:解决了程序的扩展性,使程序的扩展和维护变得简单,并且大大提高程序开发效率,基于面向对象的程序可以使他人更加容易理解你的代码逻辑。
缺点:可控性差,无法像面向过程的程序设计流水线式的可以很精确地预测问题的处理流程和结果。
二、类和对象
类:具有相同属性和方法的一类事物
对象:具体的拥有准确属性的一些变量
实例化:从一个类创造一个具体的对象的过程
类的两个作用:属性引用和实例化对象
class Person:
role = 'person'
def walk(self):
print('person in walking')
print(Person.role) #查看role属性
print(Person.walk) #引用人的走路方法,注意,不是调用
实例化:类名加上括号就是实例化,会自动出发__init__函数的运行
class Person:
role = 'person'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex =sex
def walk(self):
print('person in walking')
alex = Person('alex',18,'男') #实例化对象
print(alex.name) #查看对象属性
alex.walk() #调用对象的方法
类属性的补充
一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值 二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
三、类的命名空间和对象的命名空间
创建一个类就会创建一个类的命名空间,用来存储类中定义的所有名字,这些名字称为类的属性
类有两种属性:静态属性和动态属性。静态属性是在类中定义的变量,动态属性是在类中定义的方法
创建一个对象就会创建一个对象的命名空间,存放对象的名字,称为对象的属性
在obj.name会先从自己的命名空间找name,找不到则去类中找,类也找不到就找父类,最后找不到就抛出异常
修改变量:如果是可变数据类型中的元素进行修改,那么全局生效
如果是对变量进行重新赋值,那么只是在对象自己的命名空间里增加了一个新的属性
#设计一个类,统计这个类被实例化的次数,且所有对象共享这个属性 class Foo:
count = 0
def __init__(self):
Foo.count += 1
f1 = Foo()
print(f1.count) #
f2 = Foo()
print(f2.count) #
f3 = Foo()
print(f3.count) #
四、面向对象的组合用法
在一个类中以另一个类的对象作为数据属性,称为类的组合。
将一个类的对象拥有的属性,再将其定义成一个类以提高代码的复用性。
计算圆环的周长面积,定义一个圆类,计算圆的的周长和面积,再定义一个圆环类,将外圆和内圆的周长和面积传入,得到圆环的周长和面积
from math import pi
class Circle: #定义一个圆形类
def __init__(self,r):
self.radius = r
def perimeter(self):
return 2*pi*self.radius #计算周长
def area(self):
return pi*(self.radius**2) #计算面积 class Ring: #定义一个圆环类
def __init__(self,outer_r,inner_r):
self.outer_circle = Circle(outer_r) #把圆形类的对象当作圆环类的属性
self.inner_circle = Circle(inner_r)
def perimeter(self):
return self.outer_circle.perimeter() + self.inner_circle.perimeter()
def area(self):
return self.outer_circle.area() - self.inner_circle.area()
五、面向对象的三大特性
1.继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
python中的继承分为:单继承和多继承
class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): #多继承,用逗号分隔开
pass
查看继承:__base__只查看从左到右的继承的第一个父类,__bases__查看所有继承的父类,并以元组方式显示
如果没有指定基类,python的类会默认继承Object类,Object是python所有类的基类
继承和抽象:先抽象再继承
抽象最主要的功能是划分类别,继承是基于抽象的结果,通过编程语言去实现。
子类继承父类你使用父类的属性和方法
class Animal: #定义一个父类
def __init__(self,name,aggr,life_value): #定义父类属性
self.name = name
self.aggr = aggr
self.life_value = life_value
def eat(self): #当以父类方法
self.life_value += 100
print('%s add life_value'%self.name) class Person(Animal): #继承父类
def __init__(self,name,aggr,life_value,money):
Animal.__init__(self,name,aggr,life_value) #调用父类属性
self.money = money
def eat(self):
print('%s is eating'%self.name) class Dog(Animal):
def __init__(self,name,aggr,breed,life_value): #调用父类属性
Animal.__init__(self,name,aggr,life_value)
self.breed = breed james = Person('james',50,250,100)
flower = Dog('flower',99,'hashiqi',500)
print(james.life_value) #调用父类属性
james.eat() #如果方法重名,调用子类方法
flower.eat() #调用父类方法
print(flower.life_value)
Animal.eat(james) #调用父类方法
class Animal:
def __init__(self,name,aggr,life_value):
self.name = name
self.aggr = aggr
self.life_value = life_value
def eat(self):
self.life_value += 100
print('%s add life_value'%self.name) class Person(Animal):
def __init__(self,name,aggr,life_value,money):
Animal.__init__(self,name,aggr,life_value)
self.money = money
def eat(self):
print('%s is eating'%self.name)
Animal.eat(self) #调用父类的方法 james = Person('james',50,250,100)
james.eat() #同时调用子类和父类的方法
派生属性:父类没有的属性
派生方法:父类没有的方法
经典类使用父类的方法:父类名.方法名(子类对象) 例如:Animal.eat(snoopy)
新式类使用父类的方法:super(子类名,self).父类方法名(),例如:super(Dog,self).eat()
class Animal:
def __init__(self,name,aggr,life_value):
self.name = name
self.aggr = aggr
self.life_value = life_value
def eat(self):
self.life_value += 100
print('%s add life_value'%self.name) class Person(Animal):
def __init__(self,name,aggr,life_value,money):
super(Person,self).__init__(name,aggr,life_value) #调用父类属性
self.money = money
def eat(self):
print('%s is eating'%self.name)
super(Person,self).eat() #调用父类的方法 class Dog(Animal):
def __init__(self,name,aggr,breed,life_value):
super(Dog,self).__init__(name,aggr,life_value) #调用父类属性
self.breed = breed james = Person('james',50,250,100)
flower = Dog('flower',99,'hashiqi',500)
print(james.life_value) #调用父类属性
james.eat() #同时调用子类和父类的方法
钻石继承问题
经典类:深度优先
新式类:广度优先,查看继承顺序:模块名.mro()
接口类:是规范子类的一个模板,接口类一般只定义方法,不实现功能,只要接口类中定义的,就应该出现在子类中
接口类不能被实例化,只能被继承
支持多继承
java不支持多继承,用Interface关键字来声名接口
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): #模板,接口类
@abstractmethod #装饰接口类中方法的,加上这个装饰器,自动检测子类中的方法名
def pay(self,money):pass #定义函数不实习功能 class Apple_Pay(Payment): #继承接口类
def pay(self,money):
print('您使用苹果支付支付了%s元'%money) #实现功能 class Ali_Pay(Payment):
def pay(self, money):
print('您使用支付宝支付了%s元' % money) class WeChat_Pay(Payment):
def pay(self,money):
print('您使用微信支付了%s元' % money) def pay(obj,money):
return obj.pay(money) #多态,根据传入对象的不同,自动调用不同类的方法 apple = Apple_Pay()
pay(apple,100) #您使用苹果支付支付了100元
抽象类:抽象类可以实现子类一些共有的功能和属性,抽象类不鼓励多继承
抽象类不能被实例化
这个抽象类可以规范子类必须实现抽象类的抽象方法
from abc import ABCMeta,abstractmethod #导入模块的方法
class Base(classmethod=ABCMeta): #定义一个抽象类
def __init__(self,filename):
self.filename =filename
@abstractmethod
def open(self): #定义方法,可以实现功能
return 'file handler' @abstractmethod #定义多个方法
def close(self):pass @abstractmethod
def read(self):pass @abstractmethod
def write(self):pass class File(Base): #继承抽象类,抽象类的所有方法都要继承
def open(self):pass
def close(self):pass
def read(self):pass
def write(self):pass
2.多态
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
class Person():
def attack(self):
print('person attack dog') class Dog():
def attack(self):
print('dog attack person') def attack(obj): #多态,根据传入不同的类对象执行不同的类方法
obj.attack() person = Person()
dog = Dog()
attack(person) #person attack dog
attack(dog) #dog attack person
3.封装
封装:将一些方法和属性放到类里,这本身就是一种封装。
把属性和方法藏在类里,只能在类内部调用,不能在外部使用。
定义一个私有属性\方法:__名字
在类外部不能直接使用,如果一定要用,在私有方法之前加上:_类名__名字
在类外的名字,可以通过__dict__就可以查看
class Dog:
__role = 'dog' #私有的静态属性
def __discount(self): #私有的方法
print('in func') def price(self):
self.__discount()
print(Dog.__dict__)
print(Dog._Dog__role)
Python学习(十二) —— 面向对象的更多相关文章
- 初学 Python(十二)——高阶函数
初学 Python(十二)--高阶函数 初学 Python,主要整理一些学习到的知识点,这次是高阶函数. #-*- coding:utf-8 -*- ''''' 话说高阶函数: 能用函数作为参数的函数 ...
- Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)
Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理) 一丶封装 , 多态 封装: 将一些东西封装到一个地方,你还可以取出来( ...
- Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)
Python进阶(十五)----面向对象之~继承 一丶面向对象的三大特性:封装,继承,多态 二丶什么是继承 # 什么是继承 # b 继承 a ,b是a的子类 派生类 , a是b的超类 基类 父类 # ...
- (转)SpringMVC学习(十二)——SpringMVC中的拦截器
http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...
- Python进阶(十二)----re模块
Python进阶(十二)----re模块 一丶re模块 re模块是python将正则表达式封装之后的一个模块.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. #正则表达式: ...
- python学习(二)—简明python教程
2016-04-14 20:55:16 八.模块 简介 前面介绍了如何在程序中定义一次函数而重用代码.在其他程序中重用很多函数,就需要使用模块.模块基本上就是一个包含了所有你定义的函数和变量的文件.模 ...
- Python 第十二篇:HTML基础
一:基础知识: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标记).相当于定义统一的一套规则,大家都来遵守他,这样就可 ...
- Python学习(二)Python 简介
Python 简介 官方指南及文档 Python2.7官方指南(中文版):http://pan.baidu.com/s/1dDm18xr Python3.4官方指南(中文版):http://pan.b ...
- 编程语言与Python学习(二)
1.1 流程控制之for循环 1 迭代式循环:for,语法如下 for i in range(10): 缩进的代码块 2 break与continue(同上) 3 循环嵌套 for i in rang ...
- Python爬虫(十二)_XPath与lxml类库
Python学习指南 有同学说,我正则用的不好,处理HTML文档很累,有没有其他的方法? 有!那就是XPath,我们可以用先将HTML文档转换成XML文档,然后用XPath查找HTML节点或元素. 什 ...
随机推荐
- PHP一维数组转二维数组正则表达式
2017年11月20日17:17:08 array(1 => '哈哈') 变成 array('id' => 1, 'name' => '哈哈') 查找目标: (\d)\s=&g ...
- HNU 2015暑期新队员训练赛2 B Combination
先转化出求 Cnr中有多少奇数 其实就是 (n 的二进制数中 1 的个数为 k ,则这个奇数为 2 ^ k) 因为数很大, 故要快速求出区间的奇数 然后求 0 – low-1 的奇数, 0- high ...
- workflow的简介
工作流(Workflow) 是对工作流程及其各操作步骤之间业务规则的抽象.概括描述.工作流建模,即将工作流程中的工作如何前后组织在一起的逻辑和规则,在计算机中以恰当的模型表达并对其实施计算. 工作流要 ...
- 执行原生SQL语句的方式
原生sql语句 cursor方法:from api.models import *from django.db import connection,connectionscursor=connecti ...
- Gradle更小、更快构建APP的奇淫技巧
本文已获得原作者授权同意,翻译以及转载原文链接:Build your Android app Faster and Smaller than ever作者:Jirawatee译文链接:Gradle更小 ...
- Confluence 6 log4j 日志级别
日志级别 DEBUG - 被设计为用来获得最多的信息和事件,在对应用程序进行调试的时候,这个日志级别通常能够提供最多的有效信息(查看应用程序怎么了) INFO - 有关系统正常运行-计划任务运行,服务 ...
- LeetCode(106):从中序与后序遍历序列构造二叉树
Medium! 题目描述: 根据一棵树的中序遍历与后序遍历构造二叉树. 注意:你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorder = [9,3,15,20,7] 后序遍历 posto ...
- 新增 修改,对xx名字或者其他属性做校验判断是否存在
需求描述:页面输入完xxName和xx编码,点击提交,根据两项内容做重复校验(就是看看数据库里有木有相同的) 解决思路:把这两个东西作为查询条件去查,查到有记录,提示已存在,就不执行新增或者修改操作. ...
- java概念基础笔记整理
1.构造方法没有类型,有类型的不是不叫构造方法. 2.一个类的的成员变量可以是java允许的任何数据类型,一个类可以把某个对象作为自己的一个成员变量,如果用这样的类创建对象,那么该对象中就会其他对象, ...
- 使用gulp进行代码压缩
gulp是一个很不错的前端自动化工具,可以帮我们完成一些重复性操作,比如html.css和js代码的压缩.合并.混淆等,虽然这些操作可以通过一些在线工具帮我们实现,但不断重复地复制粘贴肯定比不上一句命 ...