python基础教程学习笔记九

来源:互联网 发布:震爆弹升级数据 编辑:程序博客网 时间:2024/05/29 14:09

 

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

 

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

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

 

 

0 0
原创粉丝点击