• Python类的进阶.md


    属性绑定

    • 在python中可以给类对象动态的绑定属性
    • 但是由于这种特性,随意动态绑定也会带来麻烦,因此可用__slots__来限制可绑定的属性名称
    • __slots__的绑定对于子类是不生效的,只对当前类实例生效
    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    
    class Man(object):
        def __init__(self, name):
            self.name = name
    
    class Woman(object):
        #限制绑定的属性名称为name和age,除此之外均不可
        __slots__ = ('name', 'age')
    
    class PrintInfo(object):
        def testMain():
            m = Man('zhangsan')
            #给m绑定name和age
            m.age = 20
            m.hight = 180
            print(m.age, m.hight)
    
            #给w绑定变量,但是hight在绑定列表之外,所以会报错
            w = Woman()
            w.name = 'lisi'
            w.age = 20
            w.hight = 180
            print(w.name, w.age, w.hight)
    
    
    if __name__ == '__main__':
        PrintInfo.testMain()
    

    属性@property

    • 使用@property来定义类的属性,可以对属性进行限制和检查:
    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    
    class Man(object):
        #给age赋一个不可变的值
        _age = 20
        _name = ''
    
        #定义age的@property属性
        @property
        def age(self):
            #注意这里的写法
            return self._age
    
        #定义name的属性
        @property
        def name(self):
            return self._name
    
        #定义name的setter方法
        @name.setter
        def name(self, value):
            if not isinstance(value, str):
                raise ValueError('name must be a str')
            self._name = value
    
    class PrintInfo(object):
        def testMain():
            m = Man()
            print(m.age)
            #这一句会报错,因为没有对age定义age的setter方法
            #m.age = 30
    
            print(m.name)
            m.name = 'wangwu'
            print(m.name)
    
    
    
    if __name__ == '__main__':
        PrintInfo.testMain()
    
    

    多继承和Mixin模式

    python支持多继承,只需要将继承的类放到定定义中
    但是在设计中一个类职责尽量单一,即使有需要增加其他功能,不要通过多重继承来实现。这样的话会增加代码的复杂度。在这里使用Mixin模式通过组合的形式来实现功能

    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    #定义主类
    class Aniaml(object):
        def isAnimal(self):
            print( 'i am an animal')
    
    
    #定义不同的功能类,注意,这些功能类职责要单一
    #这些类名统一的规则用Mixin作为后缀是为了方便维护和理解,一看就能知道使用了Mixin模式
    class FlyMixin(object):
        def isFly(self):
            print( 'i can fly')
    
    class RunMixin(object):
        def isRun(self):
            print( 'i can run')
    
    class PrintInfo(object):
        def testMain():
            pass
    
    #定义实现类,使用了Mixin模式,具备了各种功能
    class Bird(Aniaml, RunMixin, FlyMixin):
        pass
    
    #只继承了基类,所以不支持各种功能
    class Man(Aniaml):
        pass
    
    class PrintInfo(object):
        def testMain(self):
            print('Bird:')
            b = Bird()
            b.isAnimal()
            b.isFly()
            b.isRun()
    
            print('man:')
            m = Man()
            m.isRun()
    
    if __name__ == '__main__':
        p = PrintInfo()
        p.testMain()
    
    
    

    类的输出:str__和__repr

    在日志或者调试中需要打印类的信息,可以重写__str__方法来实现:

    
    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    #定义主类
    class Aniaml(object):
        def isAnimal(self):
            print( 'i am an animal')
    
        #重写Animal类的打印信息,此方法用于输出,对用户
        def __str__(self):
            return "This is class Animal."
    
        #重写了__repr__方法,此方法用于调试输出
        def __repr__(self):
            return 'This is class Animal.'
    
    
    class PrintInfo(object):
        def testMain(self):
            a = Aniaml()
            #调用了__str__方法
            print(a)
    
    if __name__ == '__main__':
        p = PrintInfo()
        p.testMain()
    
    

    类的迭代器__iter__

    iter

    Python中类可以在for循环中迭代,类中实现了__iter__()方法即可以在循环中返回迭代对象。和__iter__()方法匹配的还有__next__()方法,二者需要同时完成。

    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    class AutoLoop(object):
        def __init__(self, maxNum):
            #这里定义了变量,所以后面变量都需要用self.var的形式
            self.maxNum = maxNum
            self._startNum = 0
    
        #定义这个类的迭代器,必须返回自己
        def __iter__(self):
            return self;
    
        #next方法也是必须实现的
        def __next__(self):
            #循环的执行体
            self._startNum += 1
            #循环退出的条件,必须有
            if self.maxNum < self._startNum:
                #退出循环,固定
                raise StopIteration()
            #每次循环的返回值
            return self._startNum
    
    
    if __name__ == '__main__':
        #a = AutoLoop(6
        for n in AutoLoop(6):
            print(n)
    
    

    类的迭代器-获取指定元素:getitem()

    重写_getitem__()方法可以让刚才的例子像list一样通过下标获取指定位置元素的值:

    #对于模块Animal.py的说明
    'a demo of class type'
    #作者
    __author__  = 'liyue'
    
    class AutoLoop(object):
        def __init__(self, maxNum):
            #这里定义了变量,所以后面变量都需要用self.var的形式
            self.maxNum = maxNum
            self._startNum = 0
    
        #定义这个类的迭代器,必须返回自己
        def __iter__(self):
            return self;
    
        #next方法也是必须实现的
        def __next__(self):
            #循环的执行体
            self._startNum += 1
            #循环退出的条件,必须有
            if self.maxNum < self._startNum:
                #退出循环,固定
                raise StopIteration()
            #每次循环的返回值
            return self._startNum
    
        #取第n个元素
        def __getitem__(self, n):
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
    
    if __name__ == '__main__':
        #a = AutoLoop(6
        for n in AutoLoop(6):
            print(n)
    
        a = AutoLoop(8)
        print('取类中的第二个元素的值:%d' % a[2])
    
    

    这里还可以实现list的切片方法:

    #...
    def __getitem__(self, n):
            if isinstance(n, int): # n是索引
                a, b = 1, 1
                for x in range(n):
                    a, b = b, a + b
                return a
            if isinstance(n, slice): # n是切片
                start = n.start
                stop = n.stop
                if start is None:
                    start = 0
                a, b = 1, 1
                L = []
                for x in range(stop):
                    if x >= start:
                        L.append(a)
                    a, b = b, a + b
                return L
    #...
    

    同理__getitem__()的参数检查还要继续完善,才是一个健壮的函数。对于类来说还有__setitem__()和__delitem__()方法可以实现。

    枚举类

    从Enum派生出我们自己的自定义类,并用@unqire关键字限制重复的枚举对象;

    #导入枚举包
    from enum import Enum, unique
    'a enum class'
    
    __author__ = 'liyue'
    
    #unique关键字检查重复
    @unique
    class Wether(Enum):
        Sunny = 0
        Rain = 1
        Snow = 2
    
    
    if __name__ == '__main__':
        w1 = Wether.Sunny
        print(w1)
        print(w1.value)
    
    
  • 相关阅读:
    命名是个技术活(转)
    我想知道的是这个月哪种商品销售量最高,比上个月怎么样?销量近几个月的走势是什么?有没有未达标的?有没有超额完成的?超额完成了多少?我可不关心这个月到底售出了多少件,几点售出的,谁买的(转)
    一个demo
    oracle 创建字段自增长——两种实现方式汇总(转)
    Ruby 一些经常使用的细节
    CMap与hash_map效率对照
    Unity 4.5.2 for Mac 下载+安装+破解
    Android中View绘制流程以及invalidate()等相关方法分析
    Android Studio 100 tips and tricks
    JavaScript-2.2 document.write 输出到页面的内容
  • 原文地址:https://www.cnblogs.com/bugstar/p/7999594.html
Copyright © 2020-2023  润新知