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

  • 相关阅读:
    使用JavaScriptSerializer进行JSON序列化
    清除浮动
    后台请求url数据
    设置Response中的ContentType
    javascript阻止事件冒泡
    如何启动Nunit的调试功能
    AjaxControlToolKit(整理)二···(全部源代码)
    DataRow对象数据绑定问题
    修改程序之感悟
    关于虚函数一个很好的解释
  • 原文地址:https://www.cnblogs.com/retacn-yue/p/6194202.html
Copyright © 2020-2023  润新知