`

Python基础教程之第9章 魔法方法, 属性和迭代器

阅读更多
#魔法方法, 属性 和 迭代器
D:\>python
Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
#9.1准备工作
>>> __metaclass__=type
>>> class NewStyle(object):
...     pass # more_code_here
...
>>> class OldStyle:
...     pass # more_code_here
...
#9.2 构造器(constructor)
>>> class FooBar:
...     def __init__(self):
...             self.somevar = 42
...
>>> f = FooBar()
>>> f.somevar
42
>>>
>>> class FooBar:
...     def __init__(self, value=42):
...             self.somevar = value
...
>>> f = FooBar('This is a constructor argument')
>>> f.somevar
'This is a constructor argument'

#9.2.1 重写一般方法和特殊的constructor
>>> class A:
...     def hello(self):
...             print "Hello, I'm A."
...
>>> class B(A):
...     pass
...
>>> a = A()
>>> b = B()
>>> a.hello()
Hello, I'm A.
>>> b.hello()
Hello, I'm A.
>>>
>>> class B(A):
...     def hello(self):
...             print "Hello, I'm B"
...
>>> b = B()
>>> b.hello()
Hello, I'm B

>>> class Bird:
...     def __init__(self):
...             self.hungry = True
...     def eat(self):
...             if self.hungry:
...                     print 'Aaaah...'
...             else:
...                     print 'No, thanks!'
...
>>> class Bird:
...     def __init__(self):
...             self.hungry = True
...     def eat(self):
...             if self.hungry:
...                     print 'Aaaah...'
...                     self.hungry = False
...             else:
...                     print 'No, thanks!'
...
>>> b = Bird()
>>> b.eat()
Aaaah...
>>> b.eat()
No, thanks!
>>> class SongBird(Bird):
...     def __init__(self):
...             self.sound = 'Squawk!'
...     def sing(self):
...             print self.sound
...
>>> sb = SongBird()
>>> sb.sing()
Squawk!
>>> sb.eat()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in eat
AttributeError: 'SongBird' object has no attribute 'hungry'
>>>
#9.2 调用未绑定的超类构造器
>>> class SongBird(Bird):
...     def __init__(self):
...             Bird.__init__(self)
...             self.sound='Squark!'
...     def sing(self):
...             print self.sound
...
>>> sb = SongBird()
>>> sb.sing()
Squark!
>>> sb.eat()
Aaaah...
>>> sb.eat()
No, thanks!

#9.2 使用super函数
#conding = utf-8
__metaclass__ = type # super() only works in new style classes
class Bird:
	def __init__(self):
		self.hungry = True
	def eat(self):
		if self.hungry:
			print 'Aaaah...'
			self.hungry = False
		else:
			print 'No, thanks!'

class SongBird(Bird):
	def __init__(self):
		super(SongBird, self).__init__() # 在Python 3.0 中, super函数可以不用任何参数进行调用, 功能依然具有"魔力"
		self.sound = 'Squark!'
	def sing(self):
		print self.sound
		
sb = SongBird()
sb.sing()
sb.eat()
sb.eat()

#python tt.py
#Squark!
#Aaaah...
#No, thanks!

#9.3 成员访问
#9.3.1 基本的序列和映射规则
#coding = utf-8
def checkIndex(key):
	"""
	所给的键时能接受的索引吗?
	为了能被接受, 键应该是一个非负的整数. 如果它不是一个整数, 会引发TypeError; 如果它是负数, 则会引发IndexError(因为序列是无限长的)
	"""
	if not isinstance(key, (int, long)): raise TypeError
	if key<0: raise IndexError
	
class ArithmeticSequence:
	def __init__(self, start=0, step=1):
		"""
		初始化算术序列
		起始值:序列中的第一个值
		步长: 两个相邻值之间的差别
		改变: 用户修改的值的字典
		"""
		
		self.start = start 		#保存开始值
		self.step = step		#保存步长值
		self.changed = {} 		#没有项被修改

	def __getitem__(self, key):
		"""
		Get an item from the arithmetic sequence.
		"""
		checkIndex(key)
		try: return self.changed[key]			#修改了吗?
		except KeyError:						#否则...
			return self.start + key*self.step	#...计算值
			
	def __setitem__(self, key,  value):
		"""
		修改算术序列中的一个项
		"""
		checkIndex(key)
		self.changed[key]=value # 保存更改后的值
		
s = ArithmeticSequence(1, 2)
print s[0]
print s[1]
print s[2]
print s[3]
print s[4]

s[4]=2
print s[4]

print s[5]

#del s[4]
#Traceback (most recent call last):
#  File "tta.py", line 51, in <module>
#    del s[4]
#AttributeError: ArithmeticSequence instance has no attribute '__delitem__'

#print s["four"]
#Traceback (most recent call last):
#  File "tta.py", line 57, in <module>
#    s["four"]
#  File "tta.py", line 27, in __getitem__
#    checkIndex(key)
#  File "tta.py", line 7, in checkIndex
#    if not isinstance(key, (int, long)): raise TypeError
#TypeError

#print s[-42]
#Traceback (most recent call last):
#  File "tta.py", line 67, in <module>
#    print s[-42]
#  File "tta.py", line 27, in __getitem__
#    checkIndex(key)
#  File "tta.py", line 8, in checkIndex
#    if key<0: raise IndexError
#IndexError

#9.3.2 对列表, 字典和字符串进行子类化

>>> class CounterList(list):
...     def __init__(self, *args):
...             super(CounterList, self).__init__(*args)
...             self.counter = 0
...     def __getitem__(self, index):
...             self.counter += 1
...             return super(CounterList, self).__getitem__(index)
...
>>> c1 = CounterList(range(10))
>>> c1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> c1.reverse()
>>> c1
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> del c1[3:6]
>>> c1
[9, 8, 7, 3, 2, 1, 0]
>>> c1.counter
0
>>> c1[4] + c1[2]
9
>>> c1.counter
2

#9.4更多魔力 http://www.python.org/doc/ref/specialnames.html

#9.5 属性
>>> class Rectangle:
...     def __init__(self):
...             self.width=0
...             self.height=0
...     def setSize(self, size):
...             self.width, self.height = size
...     def getSize(self):
...             return self.width, self.height
...
>>> r = Rectangle()
>>> r.width=10
>>> r.height=5
>>> r.getSize()
(10, 5)
>>> r.setSize(150, 100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: setSize() takes exactly 2 arguments (3 given)
>>> r.setSize((150, 100))
>>> r.width
150

#9.5.1 property 函数
#幸好, Python能隐藏访问器方法, 让所有特性看起来一样. 这些通过访问器定义的特性被称为属性
__metaclass__ = type
class Rectangle:
	def __init__(self):
		self.width = 0
		self.height = 0
	def setSize(self, size):
		self.width, self.height = size
	def getSize(self):
		return self.width, self.height
	size = property(getSize, setSize)
	
r = Rectangle()
r.width = 10
r.height = 5
print r.size
r.size = 150, 100
print r.width

#python my.py
#(10, 5)
#150


#9.5.2 静态方法和类成员方法
__metaclass__ = type
class MyClass:
	def smeth():
		print 'This is a static method'
	smeth = staticmethod(smeth)
		
	def cmeth(cls):
		print 'This is a class method of', cls
	cmeth = classmethod(cmeth)
		
MyClass.smeth()
MyClass.cmeth()

#python ttb.py
#This is a static method
#This is a class method of <class '__main__.MyClass'>

__metaclass__ = type
class MyClass:
	@staticmethod
	def smeth():
		print 'This is a static method'
		
	@classmethod
	def cmeth(cls):
		print 'This is a class method of', cls
		
MyClass.smeth()
MyClass.cmeth()

#python ttc.py
#This is a static method
#This is a class method of <class '__main__.MyClass'>

#9.5.3 __getattr__, __setattr__, __delattr__ 
#__getattribute__(self, name)
#__getattr__(self, name)
#__setattr__(self, name)
#__delattr__(self, name)


class Rectangle:
	def __init__(self):
		self.width=0
		self.height=0
		
	def __setattr__(self, name,  value):
		if name == 'size':
			self.width, self.height = size
		else:
			self.__dict__[name] = value
	
	def __getattr__(self, name):
		if name == 'size':
			return self.width, self.height
		else:
			raise AttributeError
			
			

#9.6 迭代器
#9.6.1 迭代器规则
#__iter__方法返回一个迭代器(iterator), 所谓的迭代器就是具有next方法的对象. 在调用next方法时, 迭代器会返回它的下一个值.
#如果next方法被调用, 但迭代器没有值可以返回, 就会引发一个StopIteration异常

>>> class Fibs:
...     def __init__(self):
...             self.a = 0
...             self.b = 1
...     def next(self):
...             self.a, self.b = self.b, self.a+self.b
...             return self.a
...     def __iter__(self):
...             return self
...
>>> fibs = Fibs()
>>> for f in fibs:
...     if f > 1000:
...             print f
...             break
...
1597

#内建函数iter可以从可迭代的对象中获得迭代器
>>> it = iter([1,2,3])
>>> it.next()
1
>>> it.next()
2

#9.6.2 从迭代器得到序列
>>> class TestIterator:
...     value = 0
...     def next(self):
...             self.value += 1
...             if self.value > 10: raise StopIteration
...             return self.value
...     def __iter__(self):
...             return self
...
>>> ti = TestIterator()
>>> list(ti)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

#9.7 生成器
#9.7.1 创建生成器
>>> nested = [[1,2],[3,4],[5]]
>>> def flatten(nested):
...     for sublist in nested:
...             for element in sublist:
...                     yield element
...
>>> for num in flatten(nested):
...     print num
...
1
2
3
4
5
>>> list(flatten(nested))
[1, 2, 3, 4, 5]


>>> g = ((i+2)**2 for i in range(2,27))
>>> g.next()
16
>>> sum(i**2 for i in range(10))
285
>>> sum(i for i in range(1,100))
4950
>>> sum(i for i in range(1,101))
5050
>>>

#9.7.2 递归生成器
def flatten(nested):
	try:
		for sublist in nested:
			for element in flatten(sublist):
				yield element
	except TypeError:
		yield nested

print list(flatten([[[1],2],3,4,[5,[6,7]],8]))

print list(flatten([[1,2],[3,4],[5]]))

#python tte.py
#[1, 2, 3, 4, 5, 6, 7, 8]
#[1, 2, 3, 4, 5]


def flatten(nested):
	try:
		#不要迭代类似字符串的对象
		try: nested + ''
		except TypeError: pass
		else: raise TypeError
		for sublist in nested:
			for element in flatten(sublist):
				yield element
	except TypeError:
		yield nested
			
print list(flatten(['foo', ['bar', ['baz']]]))

print list(flatten([[[1],2],3,4,[5,[6,7]],8]))

print list(flatten([[1,2],[3,4],[5]]))

#['foo', 'bar', 'baz']
#[1, 2, 3, 4, 5, 6, 7, 8]
#[1, 2, 3, 4, 5]

#9.7.3 通用生成器

>>> def simple_generator():
...     yield 1
...
>>> simple_generator()
<generator object simple_generator at 0x00BBD418>
>>> simple_generator
<function simple_generator at 0x00BB2870>

#9.7.4 生成器方法
def repeater(value):
	while True:
		new = (yield value)
		if new is not None: value = new
		
r = repeater(42)
print r.next()
print r.send("Hello, world!")

#42
#Hello, world!

#9.7.5 模拟生成器
def flatten(nested):
	result = []
	try:
		# don't iterate on strings
		try: nested + ''
		except TypeError: pass
		else: raise TypeError
		for sublist in nested:
			for element in flatten(sublist):
				result.append(element)
	except TypeError:
		result.append(nested)
	return result
	
print list(flatten(['foo', ['bar', ['baz']]]))

print list(flatten([[[1],2],3,4,[5,[6,7]],8]))

print list(flatten([[1,2],[3,4],[5]]))

#['foo', 'bar', 'baz']
#[1, 2, 3, 4, 5, 6, 7, 8]
#[1, 2, 3, 4, 5]

#9.8 八皇后问题
#9.8.1 生成器和回溯
#9.8.2 问题
#9.8.3 状态表示
#9.8.4 寻找冲突
#9.8.5 基本情况
#9.8.6 需要递归的情况
#9.8.7 助手函数

# coding = utf-8
#state[0]==3, 表示在第1行的皇后是在第4列
#参数nextX代表下一个皇后的水平位置(x坐标或列), nextY代表垂直位置(y坐标或行)
def conflict(state, nextX):
	nextY = len(state)
	for i in range(nextY):
		# 如果下一个皇后和正在被考虑的当前皇后的水平距离为0(列相同)或者等于垂直距离(在一条对角线上)就返回True,否则就返回False
		if abs(state[i]-nextX) in (0, nextY-i):
			return True
	return False

def queens(num, state):
	if len(state) == num - 1:
		for pos in range(num):
			if not conflict(state, pos):
				yield pos
				
print list(queens(4, (1,3,0)))
#[2]

def queens(num, state):
	if len(state) == num - 1:
		for pos in range(num):
			if not conflict(state, pos):
				yield pos
	else:
		for pos in range(num):
			if not conflict(state, pos):
				for result in queens(num, state + (pos,)):
					yield(pos,) + result
					
def queens(num=8, state=()):
	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,) + result
					
print list(queens(3))
#[]

print list(queens(4))
#[(1, 3, 0, 2), (2, 0, 3, 1)]

for solution in queens(8):
	print solution
	#[(1, 3, 0, 2), (2, 0, 3, 1)]
#(0, 4, 7, 5, 2, 6, 1, 3)
#(0, 5, 7, 2, 6, 3, 1, 4)
#(0, 6, 3, 5, 7, 1, 4, 2)
#...
#(7, 3, 0, 2, 5, 1, 6, 4)

	
print len(list(queens(8)))
#92
def prettyprint(solution):
	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))))
#. . X . . . . .
#. . . . . X . .
#. X . . . . . .
#. . . . . . X .
#X . . . . . . .
#. . . X . . . .
#. . . . . . . X
#. . . . X . . .

print ''

prettyprint(random.choice(list(queens(4))))
#. . X .
#X . . .
#. . . X
#. X . .

#9.9 小结
#旧式类和新式类  魔法方法  构造器  重写  序列和映射  迭代器  生成器 八皇后问题
#新函数
#iter(obj)		从一个可迭代对象得到迭代器
#property(fget, fset, fdel, doc)		返回一个属性, 所有的参数都是可选的
#super(class, obj)		返回一个类的超类的绑定实例
分享到:
评论

相关推荐

    Python基础教程(第2版)第九章魔法方法、属性和迭代器.pdf

    在Python编程语言中,新式类(new-style classes)与旧式类(old-style classes)的概念主要存在于Python 2.x版本。新式类引入了一些重要的特性,如属性、super函数等,这些特性使得面向对象编程更为强大。在Python ...

    Python基础教程(第2版.修订版)

    第9章 魔法方法、属性和迭代器 第10章 充电时刻 第11章 文件和素材 第12章 图形用户界面 第13章 数据库支持 第14章 网络编程 第15章 Python和万维网 第16章 测试 第17章 扩展Python 第18章 程序打包 第19...

    python基础教程源代码-python基础教程第三版源代码.pdf

    《Python基础教程》第三版源代码是一份详细的学习资源,涵盖了Python编程的多个核心概念和实践技巧。这个源代码集合包括了从基础语法到高级特性的各种示例,旨在帮助初学者逐步掌握Python编程。 在Python的基础部分...

    python基础教程第二版(高清书签中文)

    然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器。此后探讨了如何将Python与数据库、网络、C语言等工具结合使用,从而发挥出Python的强大功能,同时介绍了Python程序测试、打包、...

    python基础教程第二版

    《Python基础教程第二版》是针对初学者的一本经典教材,尤其适合那些对Python 2.0版本感兴趣的读者。本书全面、深入地介绍了Python编程语言的基础概念和语法,旨在帮助读者掌握这一强大而灵活的编程工具。以下是根据...

    Python基础教程 第三版

    **Python基础教程第三版概述** Python是一种高级编程语言,以其简洁、易读的语法和强大的功能而闻名。作为初学者入门编程或者专业人士增强技能的工具,Python基础教程第三版是学习这一语言的理想资源。该高清版教程...

    Python基础教程(第2版 修订版)

    然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器。此后探讨了如何将Python与数据库、网络、C语言等工具结合使用,从而发挥出Python的强大功能,同时介绍了Python程序测试、打包、...

    Python基础教程(第3版). 高清 PDF

    然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器;此后探讨了如何将Python与数据库、网络、C语言等工具结合使用,从而发挥出Python的强大功能,同时介绍了Python程序测试、打包、...

    Python基础教程(第2版•修订版)

    然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器。此后探讨了如何将Python 与数据库、网络、C 语言等工具结合使用,从而发挥出Python 的强大功能,同时介绍了Python 程序测试、...

    python基础教程第二版答案-Python基础教程(第2版).pdf

    《Python基础教程(第2版)》是一本全面介绍Python编程的指南,适合初学者入门。Python作为一种解释型、面向对象、动态数据类型的高级程序设计语言,因其简洁的语法和强大的功能而广受欢迎。该书分为基础篇和高级篇...

    python基础教程廖雪峰云-Python基础教程.pdf

    Python是世界上最受欢迎的编程语言之一,尤其适合初学者入门。在Python编程中,了解脚本第一行的作用至关重要,特别是对于那些在Linux或Unix系统中工作的人来说。本文将深入讲解Python脚本首行的含义,以及如何正确...

    python基础教程配套源码

    "Python基础教程配套源码"是一份旨在帮助初学者深入理解Python编程原理和实践的资源。这个压缩包可能包含了与Python基础教程相关的各种示例代码、练习和项目,帮助学习者通过实际操作来巩固理论知识。 在Python的...

    Python语言基础:迭代器和生成器.pptx

    迭代器和生成器是Python编程中的重要概念,特别是在处理大量数据或进行高效内存管理时,它们的优势尤为明显。本文将详细讲解这两个概念及其在Python语言中的应用。 **迭代器** 迭代器是Python中访问集合元素的一种...

    python 基础教程第三版

    此外,Python的迭代器和生成器为处理大数据提供了高效的方法。 最后,Python的单元测试和调试技巧也是提升代码质量的重要手段。通过学习如何编写测试用例、使用断言以及调试工具,你可以确保代码的正确性和稳定性。...

    14.Python中的迭代器协议1

    Iterable对象和Iterator对象是Python中的两个基本概念,Iterable对象是可以被迭代的对象,而Iterator对象是Iterable对象的迭代器。 在Python中,Iterable对象可以通过`__iter__()`方法返回一个Iterator对象,而...

    python基础教程第三版前9章思维导图

    python基础教程第三版前9章的内容,学习过程中绘制了思维导图,导图工具软件是MindMaster,大于6.5版本的都可以打开

    Python基础教程(第3版) 高清PDF

    然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器;此后探讨了如何将Python与数据库、网络、C语言等工具结合使用,从而发挥出Python的强大功能,同时介绍了Python程序测试、打包、...

    Python入门基础教程全套.PPT

    Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,Python入门基础教程全套.PPT,...

    2023最新教程【樵夫教你学Python】Python全套教程 Python基础

    Python全套教程 Python基础python基础课代码+文档2023最新教程【樵夫教你学Python】Python全套教程 Python基础python基础课代码+文档2023最新教程【樵夫教你学Python】Python全套教程 Python基础python基础课代码+...

Global site tag (gtag.js) - Google Analytics