pytho基础教程笔记(7-9)(类、递归、生成器)
第七章 更加抽象
类和类型
类
概念:
__metaclass__=type # 确保类是新版的
class Person:def setName(self, name):self.name = namedef getname(self):return self.namedef greet(self):print("hello,my name is %s" % self.name)foo = Person()
bar = Person()
foo.setName("luck")
bar.setName("anakin")
foo.greet()
bar.greet()
特性、函数和方法
1.为了让方法和特性变为私有(从外部无法访问),只要在他的名字前面加上双下划线即可:
class secretive:def __inaccessible(self):'''在方法和特性变为私有,在它名字前加上双下划綫'''print ("Bet you cann't see me...")def accessible(self):print("the secret message is :")self.__inaccessible()s = secretive()
''' s.__inaccessible() # 报错,不能访问私有的特性
File "D:/Users/shirley/PycharmProjects/untitled/hm-class.py", line 26, in <module>s.__inaccessible()
AttributeError: 'secretive' object has no attribute '__inaccessible'''
s.accessible()
s._secretive__inaccessible()
'''类的内部定义中,所有以双下划线开始的名字被翻译成前面加上单下划线和类名的形式'''
注意:
类的内部定义中,所有以双下划线开始的名字被翻译成前面加上单下划线和类名的形式:
实际上还是能在类外访问这些私有的方法,尽管不应该这么做
s._secretive__inaccessible()
2.类的命名空间
定义类时,所有位于class语句中的代码都在特殊命名空间中执行–类命名空间(class namespace)。
这个命名空间可由类内所有成员访问。类的定义其实就是执行代码块。
3.指定超类
class Filter:def init(self):self.blocked =[]def filter(self, sequence):return [x for x in sequence if x not in self.blocked]class SPAMFilter(Filter): #SPAMFilter是Filter的子表def init(self): # 重写Filter超类中init方法self.blocked = ['SPAM']s= SPAMFilter()
s.init()
print(s.filter(['SPAM','SPAM','eggs','SPAM','SPAM','bacon']))
检查继承
1).查看一个类是否是另一个类的子类,内建issubclass 函数
issubclass(SPAMFilter,Filter)
2).如果想知道已知类的基类(们),是一个它的特殊特性 bases:
SPAMFilter.__bases__
3).检查一个对象是否是一个类的实例,使用isinstance方法:
isinstance(s, SPAMFilter)
4 接口和内省
接口:处理多态对象时,只关心它的接口(或称为协议)即可,即公开的方法和特性
下面是关于面向对象的一些思考:
查看对象是否存在特定特性时,try/except也很有用
第九章
构造方法
一个对象被创建之后会立即调用构造方法
# 构造方法
class FooBar:def __init__(self):self.somevar =42
f = FooBar()
print(f.somevar)
重写是继承机制中一个重要的内容,对构造方法尤其重要。构造方法用来初始化新创建对象的状态,大多数子类不仅拥有自己的初始化代码,还要拥有超类的初始化代码。
如果一个类的构造方法被重写,就需要调用超类(你所继承的类)的构造方法,否者对象可能不会被正确地初始化。
迭代器
注意:一个实现了__iter__方法的对象时可迭代的,一个实现了next方法的对象则是迭代器。
生成器
一种用普通的函数语法定义的迭代器。任何包含yield语句的函数成为生成器
八皇后问题:
'''八皇后问题'''
def conflict(state,nextX):'''1.冲突检查,在定义state时,采用state来标志每个皇后的位置,其中索引用来表示横坐标,基对应的值表示纵坐标,例如: state[0]=3,表示该皇后位于第1行的第4列上如果下一个皇后和正在考虑的前一个皇后的水平距离为0(列相同)或者等于垂直距离(在一条对角线上),返回True,否则FalsenextX:代表下一个皇后的水平位置(X坐标或者列)nextY:代表垂直位置(y坐标或者行)'''nextY = len(state)for i in range(nextY):# 如果下一个皇后的位置与当前的皇后位置相邻(包括上下,左右)或在同一对角线上,则说明有冲突,需要重新摆放if abs(state[i]-nextX) in (0,nextY -i):return Truereturn False
'''
def queens(num,state):if len(state) == num-1:for pos in range(num):if not conflict(state, pos):yield posprint (queens(4,(1,3,0)) )
'''
def queens(num = 8 ,state=()):'''2.采用生成器的方式来产生每一个皇后的位置,并用递归来实现下一个皇后的位置。如果只剩下一个皇后没有位置,那么遍历它的所有可能的位置,并且返回没有冲突发生的位置:param num: 皇后的总数:param state: 存放前面皇后的位置信息的元组:return: '''for pos in range(num):if not conflict(state, pos):# 产生当前皇后的位置信息if len(state) == num - 1:yield (pos,)# 否则,把当前皇后的位置信息,添加到状态列表里,并传递给下一皇后。else:for result in queens(num ,state+(pos,)):yield (pos,) + resultdef prettyprint(solution):"""3.打印出一个解决方案,为了直观表现棋盘,用X表示每个皇后的位置:param solution: :return: """def line(pos, length=len(solution)):return '. '*(pos)+'X '+'. '*(length-pos-1)for pos in solution:print(line(pos))import random
prettyprint(random.choice(list(queens(8))))
print(list(queens(8)))
进一步理解改问题:
关于皇后冲突的判定
用自然语言很容易描述八个皇后的位置制约关系,即棋盘的每一行,每一列,每一个条正斜线,每一条反斜线,都只能有1个皇后。如果用这个方法,判断新加入的皇后位置是否与已经存在的皇后位置冲突,先求出新皇后在哪一行,列,正反两条斜线上,再依次判断是否冲突。
发现以下规律:
在同一 ‘/’ 斜线上的位置,横纵坐标之 和 相同
在同一 ‘\’ 斜线上的位置,横纵坐标之 差 相同
由此可以很轻松的判断新皇后在正反两条斜线上是否与已经存在的皇后们的坐标冲突。
判定冲突函数
1.参数1: 之前做出的选择构成的序列(列表或元组)
2.参数2: 当前选择
3.函数目的: 判断当前选择是否与之前的选择冲突
关于判断冲突函数的写法,分两类,一种是分析棋盘上所有的棋子是否冲突,而另一种则是默认之前的棋子间不会冲突,而判断当前要检验的新棋子是否与之前的每一个棋子冲突。明显第二种实现更为简洁。
下面是冲突的判定函数
def confict(state, pos):nextY = len(state)if pos in state: return True'''判断斜线'''for i in range(nextY):if nextY-pos == i-state[i]: return Trueif nextY+pos == i+state[i]: return Truereturn False
递归“函数”
def queens(num, state=()):if num-1 == len(state):for i in range(num):if not confict(state, i):yield (i,)else:for pos in range(num):if not confict(state, pos):for result in queens(num, state+(pos,)):yield (pos,) + result# 打印结果
for i in list(queens(8)):print i
首先看参数
参数num皇后个数,第一个参数num是皇后个数,也是棋盘共num行num列。第二个参数是之前皇后的位置。 首先代码分为两部分,即if 中的内容 和 else 中的内容。
如果当前选择是最后一步, 遍历这一步能做出的所有选择,挑选出那些符合我们定义的选择。我们好像不试图从头解决这个问题,而是直接跳到最后一步来。
如果当前选择不是最后一步,那么依然遍历所有选择,当然因为不是最后一步,当前选择的可取性受制于之前的选择,并且限制了之后的选择。目光短浅的看,我们知道一些选择现在看来是合理的,但是不知道如果我们真的做此选择,会不会让后面的选择举步维艰。但是无论如何,我们只是做出当前来看可以得选择,即使后面推出当前的选择是错的,也无可厚非,因为我们正事通过这样排除所有根本不可能的,剩下的就是结果了。
先看第一个”if”代码块,代码含义显而易见,如果只剩下最后一个皇后要放置了,那么遍历棋盘上最后一行的所有位置,将符合条件的位置输出。
第一个”if”并不难,但大多初学者会被第二个”else”里的嵌套循环弄得略晕。看”else”中第一个”for”语句,没错,还是遍历当前行的所有位置,(因为第一行放皇后,第二行放皇后,第三行放皇后。。。,恰好到不是最后一行的当前行)。好吧,大多初学都被第二个”for”代码块弄晕了,yield的那个又是什么东西?
先大概说下“yield,它类似于return,但和return不同的是return 返回一个值(这个“值”可以是数值,字符串,序列等,但只是一次一个),然后函数就结束了,而yield某个值后函数不会结束,而是继续找出接下来所有符合条件的值,然后才结束。关于yield还有疑问, python基础教程书都会告诉你的。(含有yield的“函数”叫做生成器)
“yield (pos,) + result”, “pos”是当前行不与之前的皇后们冲突的位置,本质是取值0-7的整型,而在小括号里的pos再加上一个“,”表明(pos,)是只有一个元素的元组,而result也是元组,元组无法和数值类型的想家,而这就是它们可以相加的原因。
用yield而不用return的目的是我们想得到八皇后的所有位置的情况。这个”for”代码块的意思就是:如果pos这个位置可以放皇后,那么就把它放上,在此基础上,得到接下来一行行找位置把皇后放下去的所有正确结果。
八皇后问题模板与应用
接下来总结这个通用的模板:
判断冲突函数
conflict(之前的选择序列,当前的选择):'''根据具体需要进行判定即可'''
……
递归“函数”
foo(之前的选择序列):若当前是最后一次选择:遍历选择的所有取值:此次取值不与之前的选择冲突:元组(或列表)形式“返回”该值当前不是最后一次选择:遍历所有取值:不与之前的选择序列冲突:“返回”当前选择取该值的基础上,接下来的选择结果。
适用于解数独,计算某些沙盘游戏的最佳建筑布局等。
pytho基础教程笔记(7-9)(类、递归、生成器)相关推荐
- python 包用法_Python 基础教程之包和类的用法
Python 基础教程之包和类的用法 这篇文章主要介绍了 Python 基础教程之包和类的用法的相关资料, 需要的朋友可以参考下 Python 是一种面向对象.解释型计算机程序设计语言,由 Guido ...
- python基础教程笔记—即时标记(详解)
最近一直在学习python,语法部分差不多看完了,想写一写python基础教程后面的第一个项目.因为我在网上看到的别人的博客讲解都并不是特别详细,仅仅是贴一下代码,书上内容照搬一下,对于当时刚学习py ...
- Python3 基础学习笔记 C08 【类】
CSDN 课程推荐:<8小时Python零基础轻松入门>,讲师齐伟,苏州研途教育科技有限公司CTO,苏州大学应用统计专业硕士生指导委员会委员:已出版<跟老齐学Python:轻松入门& ...
- 阮一峰:jQuery官方基础教程笔记
原文地址:http://www.jobbole.com/entry.php/1151 jQuery是目前使用最广泛的javascript函数库. 据统计,全世界排名前100万的网站,有46%使用jQu ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Cytoscape基础教程笔记
昨天开始学用Cytoscape,其tutorial分为两个部分,基础的和高级 的.基础教程又分成了四课:Getting Started.Filters & Editor.Fetching Ex ...
- 绘制对象iPhone开发基础教程 笔记
每日一贴,今天的内容关键字为绘制对象 1. 虚拟内存 iPhone OS其实不会将易掉性内存(如应用程序数据)写到交换文件,因此应用程序可用内存量将受到更多的制约. Cocoa Touch供给一种内置 ...
- Python零基础教程:函数和类内建魔法属性
前言 关于对象的魔法方法我们已经讲得太多,但是对于类或函数内建的魔法属性和功能我们涉及较少,下面系统了解一下类和函数的内建属性. 查看内建属性 class Person(object):passdef ...
- iPhone开发基础教程笔记(十二)--第十二章 使用Quartz和OpenGL绘图
第十二章 使用Quartz和OpenGL绘图 有时应用程序需要能够自定义绘图.一个库是Quartz 2D,她是Core Graphics框架的一部分:另一个库是OpenGL ES,她是跨平台的图形库. ...
最新文章
- 不允许所请求的注册表访问权
- 只能在微信浏览器打开的链接,如何查看源码
- BEC listen and translation exercise 26
- bpython使用_使用Python实现一个简单的A/B测试
- 网上linux实验平台,Linux操作系统实验教程
- 常用通信时序之UART、IIC、SPI(基于STM32)
- Windows phone7 动态添加控件
- mysql服务remove失败_《MySQL数据库》MySql简介、下载与安装
- is_numeric 检测变量是否为数字或数字字符串
- python怎么用matplotlib_python-无法在我的程序中使用matplotlib函数
- java随机点名器_基于JavaScript实现随机点名器
- 2022数学建模“五一杯”B题
- NBA球队也使用Salesforce?
- HTML5网页多媒体( 音频,视频,旧版本浏览器提示,格式兼容,多媒体标签属性)
- RoboCup3D仿真2019年国赛TC笔记
- CF1144C - Two Shuffled Sequences
- 使用C++将sqlite3数据库访问封装成dsn类
- 如何创建dblink
- Tomcat 优化
- 用C#.NET 与Webdriver写的抓取网页信息的小工具
热门文章
- 超详细RestTemplate,小唐看后怒赞
- 小唐开始学 Spring Boot——(1)IDEA 2021.3.2和Maven的安装配置
- vue 重新加载当前页面
- To B 和To C 产品经理,哪个对能力要求更高?
- Mathematica应用实例——查找面积最大的10个国家并在世界地图上进行标注
- PyBullet(八)实时控制机器人手臂参数(以UR5机器人手臂为例)(有需要上传油管的视频)
- 数字签名、数字证书与CA
- 【自我管理篇】如何提高专注力
- 2022年全球市场木材粉碎机总体规模、主要生产商、主要地区、产品和应用细分研究报告
- 计量经济学及Stata应用 陈强 第十章工具变量法习题10.5