zoukankan      html  css  js  c++  java
  • Python学习10——构造函数,迭代器

    构造函数

    Pythons中的构造函数命名为__init__,在对象创建后可以自动调用它们。

    >>> class FooBar:
        def __init__(self):
            self.somever = 42
    
            
    >>> f = FooBar()
    >>> f.somever    #省略了之前f.init()的操作
    42
    >>> class FooBar:
        def __init__(self,value=42):
            self.somever = value
    
            
    >>> f = FooBar('This is a constructor argument')    #带参数的构造函数可以直接传值
    >>> f.somever
    'This is a constructor argument'

    方法重写super(SongBird,self)

    >>> class Bird:
        def __init__(self):
            self.hungry = True
        def eat(self):
            if self.hungry:
                print('eat!')
                self.hungry = False
            else:
                print('No,thanks')
    
                
    >>> b = Bird()
    >>> b.eat()
    eat!
    >>> b.eat()
    No,thanks
    
    >>> class SongBird(Bird):
        def __init__(self):
            super().__init__()    #调用super()时,将当前类和当前实例作为参数。对其返回的对象调用方法时,调用的将是超类的方法。
            self.sound = 'Squawk'
        def sing(self):
            print(self.sound)
    
            
    >>> sb = SongBird()
    >>> sb.sing()
    Squawk
    >>> sb.eat()
    eat!
    >>> sb.eat()
    No,thanks

    在上面的栗子中,SongBird类继承了超类Bird,所以SongBird类可以重写超类的构造函数。在Bird中构造函数的属性是hungry,但是SongBird类重写时只定义了属性sound,

    为了让初始化得以执行,SongBird的构造函数就必须调用超类Bird的构造函数,可以使用super函数来解决。

    元素访问

    创建一个无穷序列:

    >>> def check_index(key):   #这是一个辅助函数
        if not isinstance(key,int):raise TypeError
        if key < 0 : raise IndexError
    
        
    >>> class ArithmmeticSequence:
        def __init__(self,start=0,step=1):
            """
    初始化这个算术序列
    start--序列中的第一个值
    step---两个相邻值的差
    changed ---一个字典,包含用户修改后的值
    """
            self.start = start   #存储起始值
            self.step = step     #存储步长值
            self.changed = {}    #没有任何元素被修改
        def __getitem__(self,key):
            #从算术序列中获取第一个元素
            check_index(key)
            try:
                return self.changed[key]      #如果允许修改元素,就将修改的值保存在changed中。
            except KeyError:
                return self.start + key * self.step    #如果元素未修改,就计算值
        def __setitem__(self,key,value):
            #修改算术序列中的元素
            check_index(key)
            self.changed[key] = value      #存储修改后的值
    
            
    >>> s  = ArithmmeticSequence(1,2)
    >>> s[4]
    9
    >>> s.changed
    {}
    >>> s[4]=2   #修改元素
    >>> s[4]
    2
    >>> s[5]
    11
    >>> s.changed
    {4: 2}
    >>> s['a']
    Traceback (most recent call last):
      File "<pyshell#240>", line 1, in <module>
        s['a']
      File "<pyshell#226>", line 14, in __getitem__
        check_index(key)
      File "<pyshell#202>", line 2, in check_index
        if not isinstance(key,int):raise TypeError
    TypeError

    特殊方法:

    __len__(self):返回集合包含的项数。

    __getitem__(self):返回与指定键相关联的值。

    __setitem__(self,key,value):存储相关联的键值。(对象可变)

    __delitem__(self,key):删除与key相关联的值。(当对象可变时才需要实现这个方法)

    继承内置类型(从list,dict和str派生)

    小栗子:一个带访问计数器的列表

    >>> class CounterList(list):   #继承超类list的行为
        def __iniit__(self,*args):
            supper().__init__(*args)
            self.counter = 0
        def __getitem__(self,index):
            self.counter += 1    #每访问1次,计数加1
            return super(CounterList,self).__getitem__(index)   #返回计数
    
        
    >>> cl = CounterList(range(10))
    >>> cl
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> cl.reverse()    #可以调用超类的方法
    >>> cl
    [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    >>> del cl[3:6]
    >>> cl
    [9, 8, 7, 3, 2, 1, 0]
    >>> cl.counter    # CounterList类的counter属性初始值为0
    0
    >>> cl[4]      #访问1次列表元素,counter值加1
    4
    >>> cl.counter
    1
    >>> cl[4]+cl[2]
    6
    >>> cl.counter
    3

    特性(property:通过存取方法定义的属性。

    >>> class Rectangle:
        def __init__(self):
            self.width = 0
            self.height = 0
        def set_size(self,size):
            self.width,self.height = size
        def get_size(self):
            return self.width,self.height
    
        
    >>> r = Rectangle()
    >>> r.width = 10
    >>> r.height = 5
    >>> r.get_size()
    (10, 5)
    >>> r.set_size((30,7))
    >>> r.width
    30
    
    >>> class Rectangle:
        def __init__(self):
            self.width = 0
            self.height = 0
        def set_size(self,size):
            self.width,self.height = size
        def get_size(self):
            return self.width,self.height
        size = property(get_size,set_size)
    
        
    >>> r = Rectangle()
    >>> r.width = 30
    >>> r.height = 20
    >>> r.size
    (30, 20)
    >>> r.size = 100,150
    >>> r.width
    100

    1.调用函数property,并将存取方法作为参数(获取方法在前,设置方法在后)创建了一个特性,然后将名称size关联到这个特性。

    2.property其实是一个类。它的实例包含一些特殊方法,__get____set____delete__.

    3.在调用函数property时,可以不指定参数(特性不可读和写),指定1个参数(特性是只读的),指定2个参数(特性是可读也可写的),指定3个参数(第三个参数可选,用于删除属性的方法)。

     

    静态方法和类方法

    创建:将方法分别包装在staticmethodclassmethod类的对象中。

    静态方法无参数,直接通过类调用;类方法定义中包含cls参数(类似self),类方法也可通过对象直接调用,参数cls将自动关联到类。

    >>> 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 static method
    >>> MyClass.cmeth()
    this is a class method of  <class '__main__.MyClass'>

    上面的小栗子替换方法有点繁琐,可以优化下:装饰器可代替手动包装,在方法或函数前面使用运算符@列出这些装饰器。(指定多个装饰器时,应用顺序与列出顺序相反)

    >>> 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()
    this is a static method
    >>> MyClass.cmeth()
    this is a class method of  <class '__main__.MyClass'>

    迭代器

    方法__iter__返回一个迭代器,它是包含方法__next__的对象,而调用这个方法时可不提供任何参数。

    >>> 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):    #在迭代器中实现方法__iter__,这样迭代器就可直接用于for循环中
            return self
    
        
    >>> f = Fibs()
    >>> for i in f:
        if i > 1000:    #找出第一个大于1000的斐波那契数后停止运行
            print(i)
            break
    
        
    1597

    实现了方法__iter__的对象是可迭代的,而实现了方法__next__的对象是迭代器。

    通过对可迭代对象调用内置函数iter,可获得一个迭代器。

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

    生成器

    生成器是一种使用普通函数语法定义的迭代器。

    >>> def flatten(nested):
        for sublist in nested:     #查找列表中所有的子列表
            for element in sublist:      #按顺序迭代每个子列表的元素
                yield element        #包含yield语句的函数都被称为生成器
    
                
    >>> nested = [[1,2],[3,4],[5]]
    >>> for num in flatten(nested):
        print(num)
    
        
    1
    2
    3
    4
    5
    >>> list(flatten(nested))
    [1, 2, 3, 4, 5]

    生成器与普通函数的差别在于,生成器不是使用return返回一个值,而是可以生成多个值,每次一个。

    递归生成器

    如果有多层嵌套列表,可以用递归实现。

    >>> def fast(n):
        try:
            for sublist in n:
                for element in fast(sublist):
                    yield element
        except TypeError:
            yield n
    
            
    >>> list(fast([[1,2],3,4,[5],[6,[7]],8]))
    [1, 2, 3, 4, 5, 6, 7, 8]
  • 相关阅读:
    工厂模式
    不错公众号
    linux 下的 正则表达式(awk,sed,awk)学习
    CentOS 7 中安装 bcc-tools
    docker
    Python爬去知乎上问题下所有图片
    过滤重复数据取一条
    阿里云80端口被系统占用
    过滤重复项取时间最近的数据
    Layui的几个问题记录一下
  • 原文地址:https://www.cnblogs.com/suancaipaofan/p/11150647.html
Copyright © 2011-2022 走看看