Python系列6之面向对象
目录
- 生成器和迭代器
- 字符串格式化
- 内置函数vars
- 反射
- 面向对象编程
一. 生成器和迭代器
1. 生成器
生成器具有一种生成的能力,它仅仅代表着一种生成的能力,当我们需要使用的时候,才会通过迭代器去生成它。因为他只代表这一种生成的能力,因此,生成器比较节省内存,它一般通过yield来区分生成的位置。通过next来找到下一个位置。
# 当直接去执行genetor函数的时候,会先返回一个1,然后就退出了,因为遇到了yield
# 当用一个next之后就会执行2. 然后继续退出
# 也就是说yield其实是生成器的一个地址保存机制,只有通过next才会使他的地址指向下一个yield def genetor():
print(1)
yield 1 print(2)
yield 2 print(3)
yield 3 print(4)
yield 4
obj=genetor()
a = obj.__next__()
b = obj.__next__()
c = obj.__next__()
d = obj.__next__()
书写一个xrange函数
def xrange(args):
value = 0
while True:
if value >= args:
return
else:
yield value
value += 1
for i in xrange(5):
print(i)
2. 迭代器
迭代器代表这个一种访问的能力,他能够通过一次次的next去迭代生成器产生的对象,因此,他能够得到我们想要得到的数据。for循环就是一种迭代器。如上面的代码,我们可以通过for循环去迭代生成器。
二. 字符串格式化
1. 字符串的格式化
字符串的格式化比拼接的方式更加有效
字符串的格式化更加的方便
2. %格式化
# %的使用格式,[]里面的内容都可以省略 %[(name)][flags][width].[precision]typecode
[(name)]
格式:%[(name)][flags][width].[precision]typecode (name): 可选的,用于选择指定的key
flags: 输入的格式是左对齐还是右对齐,和width一块使用,
+ 右对齐, 正数前面加+号, 负数前面加-号
- 不变,就是左对齐
空格 不变,就是右对齐
0 右对齐,前面填充0
width 可选,占有的宽度
.precision 小数点后保留的位数
typecode
s 字符串
f 有精度的数
d 整数
事例:
s1 = "I am %+10d, age %-10d, % 10d %010d" % (10, 10, 10, 10)
s2 = "I am %+10d, age %-10d, % 10d %010d" % (-10, -10, -10, -10)
print(s1)
print(s2) 结果:
I am +10, age 10 , 10 0000000010
I am -10, age -10 , -10 -000000010
整数
# 常用事例: s1 = "I am %s" % "hu"
s2 = "I am %(name)s, age%(age)s" % {"name": "hu", "age": 13}
s3 = "3.335 + 4.2345 = %2.f" % 7.23566
print(s1, s2, s3)
3. format格式化的常用方法
[[fill]align][sign][#][0][width][,][.precision][type] 这个是format的格式,很多和%都是一样的,下面只列举一下关于它的常见用法
s1 = "i am {}, {}, {}".format("hu", "zhou", "12") s1 = "I am {}, {}, {}".format(*["hu", "zhou", "12"]) s1 = "I am {0}, {1}, {0}".format("seven", 18) s1 = "I am {0}, {1}, {0}".format(*["seven", 19]) s1 = "I am {name}, {age}, {name}".format(name="hu", age=11) s1 = "I am {name}, {age}, {name}".format(**{"name":"hu", "age":11}) s1 = "I am {:s}, {:d}, {:f}".format("hu", 18, 1823.923) s1 = "{:b},{:x},{:o}".format(10,10,10) s1 = "{:#b},{:#x},{:#o}".format(10,10,10)
三. 内置函数vars
# 内置函数的一些默认的变量 print(vars())
{'__file__': 'C:/Users/zhou/PycharmProjects/fullstack2/6_20/test.py', '__doc__': None, '__cached__': None, '__builtins__': <module 'builtins' (built-in)>, '__spec__': None, '__package__': None, '__name__': '__main__', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000063B24C4F98>}
1. __file__ 当前工作的环境的绝对路径
2. __name__ 如果是在当前工作目录,则返回的是__main__, 如果是导入的模块,返回的就是模块的名字
3. __packge__
4. __doc__ 这个变量保存的是这个文件的说明,也就是在文件开头部分对这个文件功能的说明
5. __cached__ 这个是缓存,如果是导入的模块就会有缓存
6. __builtins__ 这个是内置函数
'''
这个是一个测试文档
文档名称为test
'''
import index
print(index.__name__)
print(__name__)
print(__file__)
print(__doc__)
print(index.__cached__) 显示结果:
index
__main__
C:/Users/zhou/PycharmProjects/fullstack2/6_20/test.py 这个是一个测试文档
文档名称为test C:\Users\zhou\PycharmProjects\fullstack2\6_20\__pycache__\index.cpython-35.pyc
四. 反射
1. 反射的定义
反射就是通过字符串的形式去某个对象中操作它的成员。
2. __import__方法和import的区别
<1>. __import__可以通过字符串导入模块
<2>. import 不能通过字符串来导入模块
简单的import和__import__
# 此处s3是一个函数的名字
# 对于字符串,直接import导入会报错,
# 需要用__import__去导入,就相当于是import s3 # import "s3"
module = __import__("s3")
module.f3()
扩展的__import__, 当我们需要导入层级的模块的时候,需要用到fromlist参数
# lib目录下有个模块order,要导入的话就需要以下方法 module = __import__("lib.order", fromlist=True)
print(module.add_order())
3. 反射的方法
<1>. hasattr(模块, 关键字) 判断关键字是否在模块中,在的话返回true,不在的话返回false
<2>. getattr(模块, 关键字) 如果关键字是一个函数,则返回函数,如果是一个变量,就返回变量(里面的关键字传递的都是字符串,如果是函数,字符串默认是使用不了的,通过这个函数可以转换成使用的函数)
<3>. setattr(模块, 关键字, 值) 往模块中加入关键字,加入的可以是变量, 可以是函数,加入和删除都是在内存中完成的,并不会影响文件的内容
<4>. delattr(模块,关键字) 从模块中删除关键字
s3的内容
def f1():
print("f1") =============================
# 导入s3,判断关键字是否在s3中
import s3
ret1 = hasattr(s3, "f1")
ret2 = hasattr(s3, "f11")
print(ret1)
print(ret2) 结果:
True
False
hasattr()
# 导入模块,通过字符串得到模块内函数
# 然后执行函数
# 字符串f1 是执行不了的,只能通过getattr得到函数在执行 import s3
func = getattr(s3, 'f1')
func()
getattr()
# setattr传递的是一个键值对,而hasattr判断的只是键,而不是值,
# 因为刚开始还没有这个“name”,所以返回的是false,通过setattr设置了这个键,所以返回的是True import s3
print(hasattr(s3, "name"))
setattr(s3, "name", "hu")
print(hasattr(s3, "name")) 结果:
False
True
setattr()
# 开始f1是存在的,所以返回True
# 通过del删除之后,在返回的就是False了 import s3
print(hasattr(s3, "f1"))
delattr(s3, "f1")
print(hasattr(s3, "f1")) 结果:
True
False
delattr()
url = input("请输入url:")
target_module, target_func = url.split("/")
print(target_func, target_module)
module = __import__("lib."+target_module, fromlist=True)
print(module)
if hasattr(module, target_func):
# module.target_func()
target_func = getattr(module, target_func)
target_func()
else:
print("")
Python实例(基于web框架的路由系统)
五. 面向对象编程
1. 编程
其实在我们日常生活中,编程的方式有很多,例如:面向过程,面向对象,或者是函数式编程,他们的区别还蛮大的,但是最终的目的只有一个,那就是简化工作量。就像是盖房子,面向过程就是我要自己去买砖买瓦,自己垒砌,然后函数式编程就是我自己买砖买瓦,然后找木匠工人给我做,面向对象就是,我要直接买一套房子,省的自己做了。
2. 面向对象编程
(1). 定义类
类是什么呢?类严格的定义是由某种特定的元数据所组成的内聚的包。他是由多个函数共同组成的为了完成某种功能的组合。既然有了函数,为什么还要类呢?当我们的函数出现大量的相同的参数或者相同的功能的时候,就需要类来简化其操作了
# 关键字class创建了一个类,类名为Foo
# 定义了三个方法,__init__ f1和f2
# 方法里面的self为默认的参数,必须带 class Foo:
def __init__(self):
self.Name = "hu"
def f1(self):
print("f1")
def f2(self):
print("f1")
(2). 执行类(创建对象)
对象是什么呢?在Python中,一切皆对象,当我们创建了一类数据之后,他只是一类数据,其中的方法,参数都都是泛华的东西,我们需要有一个对象来对其进行实例化。也就是说,当我们说:这有个人。你肯定不知道他是谁,因为他只代表了一类数据,当我们说:他是李刚,你就会恍然大悟,哦 ,他是李刚啊,这是因为我们吧类实例化了。
__init__方法用来创建对象和封装内容
每一个方法中的self变量都是Python中默认添加的,用来传递对象的。当我们创建了一个obj对象的时候,会自动的调用类中的__init__方法,然后把obj当做参数传递给self。
# 通过类名加括号去创建一个对象,并用对象去调用方法 class Foo:
def __init__(self):
self.Name = "hu"
def f1(self):
print("f1")
def f2(self):
print("f1") obj = Foo()
obj.f1()
创建对象的图示:都在内存中,创建一个对象的时候,默认的会去执行类中的__init__方法,通过init方法来产生右边的对象。
(3). 三大特性
在面向对象的语言中,一般都具有以下三种特性,封装,继承和多态。也正是因为这样,才构成了一个庞大的面向对象的系统,以至于你可以通过它来表述任何事物。千变万化。
<1>. 封装
封装就是把一系列相同的功能封装到对象中,从而简化类的方法。在介绍封装之前,我们先来比较一下封装和不封装的区别。
由下面的例子我们就可以看出来,封装其实就是把一些重复的量统一的在一个地方进行定义,然后在利用。
# 没有封装数据
class Person:
def chifan(self, name, age, gender):
print(name, "吃饭")
def shuijiao(self, name, age, gender):
print(name, "睡觉")
def dadoudou(self, name, age, gender):
print(name,"打豆豆")
没有封装
class Person:
def __init__(self, name, age, gender):
self.Name = name
self.Age = age
self.Gender = gender
def chifan(self):
print(self.Name,"吃饭")
def shujiao(self):
print(self.Name,"睡觉")
def dadoudou(self):
print(self.Name,"打豆豆")
封装
使用场景:
a. 当同一类型的方法具有多个模板的时候,直接封装成对象即可
b. 把类当做模板,创建多个对象(对象内封装的数不一样)
例:定义了一个类Person,用__init__去封装了三个参数,以供下面的两个方法来调用,通过pickle模块来存档。
import pickle
class Person:
def __init__(self, name, age, weight):
self.Name = name
self.Age = age
self.Weight = weight
def chi(self):
self.Weight += 2
def jianshen(self):
self.Weight -= 1
ret = pickle.load(open('youxi', 'rb'))
if ret:
print(ret.Weight)
obj1 = Person(ret.Name, ret.Age, ret.Weight)
else:
obj1 = Person('xiaoming', 12, 200)
obj1.chi()
obj1.chi()
obj1.chi()
obj1.jianshen()
pickle.dump(obj1, open('youxi', 'wb'))
<2>. 继承
我们都听说过子承父业,其实继承就是这个意思,当我们定义了几个类之后,发现这几个类都有一些共同的属性和方法,这个时候我们就可以把这几个共同的属性和方法定义成一个类来当做这几个类的父亲,然后这几个类就可以继承父亲的属性和方法来当做自己的方法。如下面这个例子,定义了三个类,一个父类,一个儿子,一个女儿,父类的方法有吃和喝,儿子的方法是票,女儿的方法是赌,当儿子继承了父亲,就会把父亲的方法继承下来,自然也就会了吃和喝,女儿也一样。
class Parent:
def chi(self):
print("吃")
def he(self):
print("喝")
class son(Parent):
def piao(self):
print("票") class nver(Parent):
def du(self):
print("赌") obj = son()
obj.chi()
obj.he()
obj.piao()
obj1 = nver()
obj1.chi()
obj1.he()
obj1.du()
继承的规则
1. 子类会默认的继承父类的所有方法
2. 如果子类和父类有同样的方法,会优先的去用子类的方法
3. Python中可以继承多个类(这个是Python的特点, C#和java都不具备)
Python中继承多个类的顺序规则
因为Python中可以多继承,因此当子继承父类的时候,它的规则一般是先执行左边的,后执行右边的,当有嵌套的时候,每次还要重新回到子类中去递归查找。如下面的例子
例:当子类中的方法没有的时候就会依次的向上进行查找
# 创建了几个类,继承关系如上图中的一
class A:
def f1(self):
print("A")
class B:
def f1(self):
print("B")
class C(A):
def f1(self):
print("C") class D(B):
def f1(self):
print("D")
class E(C, D):
def f1(self):
print("E")
obj = E()
obj.f1()
上图一
class Hu:
def f1(self):
print("Hu")
class A(Hu):
def f1(self):
print("A")
class B(Hu):
def f1(self):
print("B")
class C(A):
def f1(self):
print("C") class D(B):
def f1(self):
print("D")
class E(C, D):
def f1(self):
print("E")
obj = E()
obj.f1()
上图二
<3>. 多态
因为在Python传参的时候本身就没有类型的约束,因此它本身就是多态的,我们可以把任意的数据传进去。
(4). 成员
方法: 静态方法(无需使用对象封装的内容@staticmethod,直接用类进行调用),普通方法(使用对象进行封装),类方法
字段: 静态字段(每一个对象都会有一份),普通字段(使用对象中进行封装的)
特性: 只有一种,将方法伪造成字段
调用成员的方式:
1. 如果没有self, 就用类进行调用
2. 如果有self, 就用对象进行调用
3. 异常处理
在程序执行的过程中,会遇到一些未知的错误,但是我们总是希望把这些错误的以我们能控的方式返回给用户,这是就用到了异常处理。
异常处理的格式:
# 当try后面的语句发生错误之后,就会触发后面的语句,返回一个我们可以控制的错误信息 a = input("输入一个数:")
try:
a = int(a)
except Exception as e:
print("出错了....")
Python系列6之面向对象的更多相关文章
- Python基础系列----函数,面向对象,异常
1.前言 前 ...
- 懂一点Python系列——快速入门
本文面相有 一定编程基础 的朋友学习,所以略过了 环境安装.IDE 搭建 等一系列简单繁琐的事情. 一.Python 简介 Python 英文原意为 "蟒蛇",直到 1989 年荷 ...
- 总结整理 -- python系列
python系列 python--基础学习(一)开发环境搭建,体验HelloWorld python--基础学习(二)判断 .循环.定义函数.继承.调用 python--基础学习(三)字符串单引号.双 ...
- Python数据结构与算法--面向对象
前面已经讲过,Python是一种面向对象的编程语言. 面向对象编程语言中最重要的特征是允许程序员创建类建立数据模型来解决问题. 我们之前利用抽象数据类型提供的逻辑来描述数据对象 (它的状态) 和功能 ...
- python笔记 - day7-1 之面向对象编程
python笔记 - day7-1 之面向对象编程 什么时候用面向对象: 多个函数的参数相同: 当某一些函数具有相同参数时,可以使用面向对象的方式,将参数值一次性的封装到对象,以后去对象中取值即可: ...
- 初探接口测试框架--python系列7
点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...
- 初探接口测试框架--python系列2
点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...
- 初探接口测试框架--python系列3
点击标题下「微信」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是我们期 ...
- 初探接口测试框架--python系列4
点击标题下「蓝色微信名」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是 ...
随机推荐
- sqlserver门户设置
------ insert by wandz 20180918 门户模板表 start ------set identity_insert oa_portal_template on;begin de ...
- [学习心得][Introduction to ASP.NET Core 1.0]4-1 Creating a Form
原视频地址https://mva.microsoft.com/en-US/training-courses/introduction-to-asp-net-core-1-0-16841?l=eYlqd ...
- 我的java开发规范
关于文件的命名参考阮一峰的这篇文章:http://www.ruanyifeng.com/blog/2017/02/filename-should-be-lowercase.html,文中说文件名全部使 ...
- centos7 gearmand-1.1.15打包rpm
wget https://github.com/gearman/gearmand/releases/download/1.1.15/gearmand-1.1.15.tar.gz -O /root/rp ...
- ansible使用4-Playbook Roles and Include Statements
task include --- # possibly saved as tasks/foo.yml - name: placeholder foo command: /bin/foo - name: ...
- NFS笔记(一)NFS服务器工作原理及详细配置
一.NFS工作原理 1.什么是NFS服务器 NFS就是Network File System的缩写,它最大的功能就是可以通过网络,让不同的机器.不同的操作系统可以共享彼此的文件. NFS服务器可以让P ...
- 笨办法学Python(十二)
习题 12:提示别人 当你键入 raw_input() 的时候,你需要键入 ( 和 ) 也就是“括号(parenthesis)”.这和你格式化输出两个以上变量时的情况有点类似,比如说 "%s ...
- 谷歌Web中文开发手冊:3响应式
https://developers.google.com/web/fundamentals/getting-started/your-first-multi-screen-site/responsi ...
- 搭建FTP服务
(一)FTP服务概述 FTP服务概述:名称.功能.特点.端口 VSFTP:very secure FTP 端口:21 服务安装#yum install vsftpd lftp -y ##lftp ...
- 【BZOJ1858】[SCOI2010] 序列操作(ODT裸题)
点此看题面 大致题意: 给你一个\(01\)序列,让你支持区间赋值.区间取反.区间求和以及求一段区间内最多有多少连续的\(1\)这些操作. \(ODT\) 这道题正解似乎是线段树,但码量较大,而且细节 ...