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节点或元素. 什 ...
随机推荐
- 关于iwinfo的调试
在调试 主动扫描时,调用命令 “iwinfo wlan0 scan”时, 在iwinfo中添加的调试语句没有打印和记录到log中去. 后查看iwinfo的makefile发现,在生成iwinfo程序 ...
- POJ 3368
题意: 给你一组数列, 查询区间内有出现次数最多的数的频数 RMQ , 对于一个区间, 分为两部分, 从 L 开始连续到 T , T + 1 到 R 显然 答案为 MAX (T – L + ...
- Laravel 5.2分页--怎么在一个页面实现两个以上的列表分页,互不影响?
今天就碰到这样的一个问题?想在一个页面里面放两个列表,并且两个列表都可以进行分页. 但是,laravel提供的分页方法很方便,可是两个以上就出问题了,当我点其中一个分页的链接时候,页面上其余的分页跟着 ...
- scp命令:远程复制粘贴文件
文章链接:https://www.cnblogs.com/webnote/p/5877920.html scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有 ...
- 使用PHP Manager for IIS时,Windws 10自带IIS注意事项
1)开启IIS 10:在“控制面板”的“程序和功能”的“启用或关闭Windows功能”内,勾选(启用)“Internet Information Services”,然后确定,进行安装. 2)若要使用 ...
- tomcat占用cpu比较多
在Linux中当Tomcat启动后,我们只是去查看应用是否能够正常访问来判断Tomcat启动是否正常.一般情况下这样看是没有问题的,但是有时候我们会发现当Tomcat使用了一段时间后,开始出现CPU或 ...
- Golang服务器热重启、热升级、热更新(safe and graceful hot-restart/reload http server)详解
服务端代码经常需要升级,对于线上系统的升级常用的做法是,通过前端的负载均衡(如nginx)来保证升级时至少有一个服务可用,依次(灰度)升级. 而另一种更方便的方法是在应用上做热重启,直接更新源码.配置 ...
- wet 下载jdk 64位
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com% ...
- SwipeRefreshLayout,用最少的代码定制最美的上下拉刷新样式
下拉刷新框架其实有很多,而且质量都比较高.但是在日常开发中,每一款产品都会有一套自己独特的一套刷新样式.相信有很多小伙伴在个性化定制中都或多或少的遇到过麻烦.今天我就给大家推荐一个在定制方面很出彩的一 ...
- Markdown 简介及基础语法
一.Markdown 简介 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式. 二.Markdown 基础语法 1. Markdown ...