python基础教程学习笔记九

第九章 魔法方法 属性和迭代器

构造方法,示例代码如下:

>>>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 aconstructor argument'

重写一般方法和特殊的构造方法

>>>class A:

def hello(self):

print ('hello ,i am A')

>>>class B(A):

pass

>>>a=A()

>>>b=B()

>>>a.hello()

hello ,i am A

>>>b.hello()

hello ,i am A

#在B中重写A 类的方法

>>>class B(A):

def hello(self):

print('hello,i am B')

>>>b=B()

>>>b.hello()

hello,i am B

调用超类的构造方法:

A 调用未绑定的超类的构造方法

B 使用super函数

重写构造方法后会出现如下情况:

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():

def __init__(self):

self.sound='squawk!'

def sing(self):

print(self.sound)

class SongBird(Bird):

def __init__(self):

self.sound='squawk!'

def sing(self):

print(self.sound)

>>>sb=SongBird()

>>>sb.sing()

squawk!

#子类在调用父类方法时,没有初始化hungry属性

>>>sb.eat()

Traceback (mostrecent call last):

File "<pyshell#78>", line 1,in <module>

sb.eat()

File "<pyshell#59>", line 5,in eat

if self.hungry:

AttributeError:'SongBird' object has no attribute 'hungry'

解决方法:

A 调用未绑定的超类的构造方法

>>>class SongBird(Bird):

def __init__(self):

Bird.__init__(self)

self.sound='squawk!'

def sing(self):

print(self.sound)

>>>sb=SongBird()

>>>sb.sing()

squawk!

>>>sb.eat()

Aaaah...

>>>sb.eat()

no,thanks

B 使用super函数

classSongBird(Bird):

def __init__(self):

super(SongBird,self).__init__()

self.sound='squawk!'

def sing(self):

print(self.sound)

>>>sb=SongBird()

>>>sb.sing()

squawk!

>>>sb.eat()

Aaaah...

>>>sb.eat()

no,thanks

访问成员

基本的序列和映射规则

可变序列的四个方法

__len__(self):

__getitem__(self,key):

__setitem__(self,key,value):

__delitem__(self,key):

def checkIndex(key):

"""

所给的键是不是参接受的索引

键应该是一个非负的整数

"""

if not isinstance(key,int):

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 form the arithmeticsequence

"""

checkIndex(key)

try:

return self.changed[key]

except KeyError:

returnself.start+key*self.step

def __setitem__(self,key,value):

"""

修改算术序列中的一个项

"""

checkIndex(key)

self.changed[key]=value #保存修改后的值

>>>s=ArithmeticSequence(1,2)

>>>s[0]

1

>>>s[4]

9

子类化列表字典和字符串

#和内建列表行为相似的序列,可以使用list

#带有访问计数的列表

class CounterList(list):

def __init__(self,*args):

super(CounterList,self).__init__(*args)

self.counter=0

def __getitem__(self,index):

self.counter+=1

returnsuper(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]

>>> delc1[3:6]

>>> c1

[9, 8, 7, 3, 2,1, 0]

>>>c1.counter

0

>>>c1[4]+c1[2]

9

>>>c1.counter

2

属性

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((100,150))

>>>r.width

100

Proterty函数

四个参数分别为:

Fget

Fset

Fdel

doc

__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.width=10

>>>r.height=5

>>>r.size

(10, 5)

>>>r.size=100,150

>>>r.size

(100, 150)

静态方法和类成员方法

Static method 没有self参数,且能够被类本身调用,

Class method 需要用cls的参数

#方式一手动包装

__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()

this is a staticmethod

>>>Myclass.cmeth()

this is a classmethod 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 methodof',cls)

>>>Myclass.smeth()

this is a staticmethod

>>>Myclass.cmeth()

this is a classmethod of <class '__main__.Myclass'>

__getattr__ __setattr__和它的朋友们

有点类似于java中的get和set方法,不同的是不用每个属性都去编写

class Rectangle:

def __init__(self):

self.width=0

self.height=0

def __setattr__(self,name,value):

if name=='size':

self.width,self.height=value

else:

self.__dict__[name]=value

def __getattr__(self,name):

if name=='size':

returnself.width,self.height

else:

raise AttributeError

迭代器

__iter__

迭代器的规则

#测试不成功

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()

>>> forf in fibs:

if f > 1000:

print(f)

break

Traceback (mostrecent call last):

File "<pyshell#15>", line 1,in <module>

for f in fibs:

TypeError:iter() returned non-iterator of type 'Fibs'

>>> it=iter([1,2,3])

#3.0 之前是使用it.next()

>>>next(it)

1

从迭代器得到序列 ????????

classTestIterator:

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)

Traceback (mostrecent call last):

File "<pyshell#34>", line 1,in <module>

list(ti)

TypeError:iter() returned non-iterator of type 'TestIterator'

生成器

创建生成器

defflatten(nested):

for sublist in nested:

for element in sublist:

yield element

>>>mested=[[1,2],[3,4],[5]]

>>> fornum in flatten(mested):

print(num)

递归生成器

如果要处理任意层的嵌套

defflatten(nested):

try:

#不要迭代类似于字符串的对象

try:

nested+''

except TypeError:pass

else:

raise TypeError

for sublist in nested:

for element inflatten(sublist):

yield element

except TypeError:

yield nested

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

[1, 2, 3, 4, 5,6, 7, 8]

通用生成器

生成器的方法

是生成器与外界交流的渠道

使用send方法就像使用next(),需要一个参数(即要发送的消息)

Send()方法只有在生成器挂起后才有意义

>>> def repeater(value):

while True:

new=(yield value)

if new is notNone:

value=new

>>> r=repeater(42)

>>> r.next()

Traceback (most recent call last):

File"<pyshell#42>", line 1, in <module>

r.next()

AttributeError: 'generator' object has no attribute 'next'

>>> r.send('hello world!')

Traceback (most recent call last):

File"<pyshell#43>", line 1, in <module>

r.send('hello world!')

TypeError: can't send non-None value to a just-started generator

在2.5以后的版本中,还有两人方法:

Throw()

Close()

模拟生成器


八皇后问题

寻找下一个没有冲突的位置

>>> defconflict(state,nextX):

nextY=len(state)

for i in range(nextY):

if abs(state[i]-nextX) in(0,nextY-i):

return True

return False

#基本情况

>>> defqueens(num,state):

if len(state)==num-1:

for pos in range(num):

if not conflict(state,pos):

yield pos

>>>list(queens(4,(1,3,0)))

[2]

需要递归的情况

defqueens(num=8,state=()):

for pos in range(num):

if not conflict(state,pos):

if len(state)==num-1:

yield (pos,)

else:

for result inqueens(num,state+(pos,)):

yield(pos,)+result

for solution inqueens(8):

print(solution)

(0, 4, 7, 5, 2,6, 1, 3)

(0, 5, 7, 2, 6,3, 1, 4)

(0, 6, 3, 5, 7,1, 4, 2)

(0, 6, 4, 7, 1,3, 5, 2)

(1, 3, 5, 7, 2,0, 6, 4)

(1, 4, 6, 0, 2,7, 5, 3)

(1, 4, 6, 3, 0,7, 5, 2)

(1, 5, 0, 6, 3,7, 2, 4)

(1, 5, 7, 2, 0,3, 6, 4)

(1, 6, 2, 5, 7,4, 0, 3)

(1, 6, 4, 7, 0,3, 5, 2)

(1, 7, 5, 0, 2,4, 6, 3)

(2, 0, 6, 4, 7,1, 3, 5)

(2, 4, 1, 7, 0,6, 3, 5)

(2, 4, 1, 7, 5,3, 6, 0)

(2, 4, 6, 0, 3,1, 7, 5)

(2, 4, 7, 3, 0,6, 1, 5)

(2, 5, 1, 4, 7, 0,6, 3)

(2, 5, 1, 6, 0,3, 7, 4)

(2, 5, 1, 6, 4,0, 7, 3)

(2, 5, 3, 0, 7,4, 6, 1)

(2, 5, 3, 1, 7,4, 6, 0)

(2, 5, 7, 0, 3,6, 4, 1)

(2, 5, 7, 0, 4,6, 1, 3)

(2, 5, 7, 1, 3,0, 6, 4)

(2, 6, 1, 7, 4,0, 3, 5)

(2, 6, 1, 7, 5,3, 0, 4)

(2, 7, 3, 6, 0,5, 1, 4)

(3, 0, 4, 7, 1,6, 2, 5)

(3, 0, 4, 7, 5,2, 6, 1)

(3, 1, 4, 7, 5,0, 2, 6)

(3, 1, 6, 2, 5,7, 0, 4)

(3, 1, 6, 2, 5,7, 4, 0)

(3, 1, 6, 4, 0,7, 5, 2)

(3, 1, 7, 4, 6,0, 2, 5)

(3, 1, 7, 5, 0,2, 4, 6)

(3, 5, 0, 4, 1,7, 2, 6)

(3, 5, 7, 1, 6,0, 2, 4)

(3, 5, 7, 2, 0,6, 4, 1)

(3, 6, 0, 7, 4,1, 5, 2)

(3, 6, 2, 7, 1,4, 0, 5)

(3, 6, 4, 1, 5,0, 2, 7)

(3, 6, 4, 2, 0,5, 7, 1)

(3, 7, 0, 2, 5,1, 6, 4)

(3, 7, 0, 4, 6,1, 5, 2)

(3, 7, 4, 2, 0,6, 1, 5)

(4, 0, 3, 5, 7,1, 6, 2)

(4, 0, 7, 3, 1,6, 2, 5)

(4, 0, 7, 5, 2,6, 1, 3)

(4, 1, 3, 5, 7,2, 0, 6)

(4, 1, 3, 6, 2,7, 5, 0)

(4, 1, 5, 0, 6,3, 7, 2)

(4, 1, 7, 0, 3,6, 2, 5)

(4, 2, 0, 5, 7,1, 3, 6)

(4, 2, 0, 6, 1,7, 5, 3)

(4, 2, 7, 3, 6,0, 5, 1)

(4, 6, 0, 2, 7,5, 3, 1)

(4, 6, 0, 3, 1,7, 5, 2)

(4, 6, 1, 3, 7,0, 2, 5)

(4, 6, 1, 5, 2,0, 3, 7)

(4, 6, 1, 5, 2,0, 7, 3)

(4, 6, 3, 0, 2,7, 5, 1)

(4, 7, 3, 0, 2,5, 1, 6)

(4, 7, 3, 0, 6,1, 5, 2)

(5, 0, 4, 1, 7,2, 6, 3)

(5, 1, 6, 0, 2,4, 7, 3)

(5, 1, 6, 0, 3,7, 4, 2)

(5, 2, 0, 6, 4,7, 1, 3)

(5, 2, 0, 7, 3,1, 6, 4)

(5, 2, 0, 7, 4,1, 3, 6)

(5, 2, 4, 6, 0,3, 1, 7)

(5, 2, 4, 7, 0,3, 1, 6)

(5, 2, 6, 1, 3,7, 0, 4)

(5, 2, 6, 1, 7,4, 0, 3)

(5, 2, 6, 3, 0,7, 1, 4)

(5, 3, 0, 4, 7,1, 6, 2)

(5, 3, 1, 7, 4,6, 0, 2)

(5, 3, 6, 0, 2,4, 1, 7)

(5, 3, 6, 0, 7,1, 4, 2)

(5, 7, 1, 3, 0,6, 4, 2)

(6, 0, 2, 7, 5,3, 1, 4)

(6, 1, 3, 0, 7,4, 2, 5)

(6, 1, 5, 2, 0,3, 7, 4)

(6, 2, 0, 5, 7,4, 1, 3)

(6, 2, 7, 1, 4,0, 5, 3)

(6, 3, 1, 4, 7,0, 2, 5)

(6, 3, 1, 7, 5,0, 2, 4)

(6, 4, 2, 0, 5,7, 1, 3)

(7, 1, 3, 0, 6,4, 2, 5)

(7, 1, 4, 2, 0,6, 3, 5)

(7, 2, 0, 5, 1,4, 6, 3)

(7, 3, 0, 2, 5,1, 6, 4)

>>> defprettyprint(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 . . . . . .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值