zoukankan      html  css  js  c++  java
  • 面向对象高级编程

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。

    使用__slots__

    Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性。

    class student(object):
        __slots__ = ('name','age')  #用tuple定义允许绑定的属性名称
    
    s=student() #创建一个student实例,并给他绑定参数
    s.name='wxy'
    s.age=20
    s.source=98
    print(s.name,s.age,s.source)
    
    输出:
    Traceback (most recent call last):
      File "/home/wangxy/PycharmProjects/LearnPython/sample/oop-advanced/slots.py", line 7, in <module>
        s.source=98
    AttributeError: 'student' object has no attribute 'source'

    使用@property

    有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!

    还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

    class stu(object):
    
        @property  #python 内置装饰器,负责把一个getter方法变成属性调用
        def score(self):
            return self._score
    
    
        @score.setter #property本身创造的另一个装饰器score.setter
        def score(self,value): #传入对象,值
            if not isinstance(value,int): #检查值的数据类型是否为int
                raise ValueError('sroce must be an integer') #raise语句可以触发异常,如果value不是int则触发参数异常
            if value<0 or value>100:
                raise ValueError('score must between 0 ~ 100!')
            self._score=value
    
    
    s=stu()
    
    s.score=60
    print(s.score)

    还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

    #使用property定义一个只读属性
    class vip(object):
    
        @property
        def birth(self):
            return self._birth
    
        @birth.setter
        def birth(self,value):
            self._birth=value
    
        #age只定义getter方法,不定义setter方法就是只读属性
        @property
        def age(self):
            return 2017-self._birth
    #练习:请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution:
    class screen(object):
        @property
        def width(self):
            return self._width
    
        @width.setter
        def width(self,value):
            if not isinstance(value,int):
                raise ValueError('width must be an integer')
            self._width=value
    
        @property
        def high(self):
            return self._high
    
        @high.setter
        def high(self, value):
            if not isinstance(value, int):
                raise ValueError('high must be an integer')
            self._high = value
    
        @property
        def resolution(self):
            return self._width * self._high
    
    
    # 测试:
    s = screen()
    s.width = 1024
    s.high = 768
    print('resolution =', s.resolution)
    if s.resolution == 786432:
        print('测试通过!')
    else:
        print('测试失败!')

    多重继承

    通过多重继承,一个子类就可以同时获得多个父类的所有功能。

    在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为MixIn。

    class Animal(object):
        pass
    #定义哺乳动物大类
    class Mammal(Animal):
        pass
    
    #定义鸟类大类
    class Bird(Animal):
        pass
    
    #定义动物功能类
    class RunnableMixIn(object):
        def run(self):
            print("Running……")
    
    #定义动物功能飞
    class FlyableMixIn(object):
        def fly(self):
            print("Flying……")
    
    
    #定义动物生活习惯吃肉
    class CarnivorousMixIn(object):
        pass
    
    #定义动物生活习惯吃草
    class HerbivoresMixIn(object):
        pass
    
    
    #使用多重继承定义一个多功能类
    
    class dog(Mammal,RunnableMixIn,CarnivorousMixIn):
        pass
    
    d=dog()
    d.run()

    由于Python允许使用多重继承,因此,MixIn就是一种常见的设计。

    只允许单一继承的语言(如Java)不能使用MixIn的设计。

    定制类

    使用枚举类(http://www.cnblogs.com/ucos/p/5896861.html)

    为枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能:

    #对Enum的第一种使用
    from enum import Enum
    
    month=Enum('month',('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
    
    for name,member in month._member_map_.items():
        print(name, '=>', member, ',', member.value)
    
    输出:
    Jan => month.Jan , 1
    Feb => month.Feb , 2
    Mar => month.Mar , 3
    Apr => month.Apr , 4
    May => month.May , 5
    Jun => month.Jun , 6
    Jul => month.Jul , 7
    Aug => month.Aug , 8
    Sep => month.Sep , 9
    Oct => month.Oct , 10
    Nov => month.Nov , 11
    Dec => month.Dec , 12
    #如果需要更精准的控制枚举类型,可以从Enum类生出自定义类
    @unique
    class Weekday(Enum):
        Sun = 0  # Sun的value被设定为0
        Mon = 1
        Tue = 2
        Wed = 3
        Thu = 4
        Fri = 5
        Sat = 6
    
    
    #既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。
    print(Weekday.Mon.value)
    print(Weekday(3))

    使用元类

     

  • 相关阅读:
    Java日期时间API系列1-----Jdk7及以前的日期时间类
    Redis设置密码,保护数据安全
    Java SE 8 并发增强
    Java8并发教程:Threads和Executors
    MySQL5.7增量备份恢复全实战
    HashSet HashMap 源码阅读笔记
    操作系统知识点
    Window批处理命令
    JS典型题
    SiteMesh装饰模式
  • 原文地址:https://www.cnblogs.com/wangxy92/p/7993752.html
Copyright © 2011-2022 走看看