首页 > 编程语言 > 详细

Python面向对象进阶

时间:2021-07-21 12:04:48      阅读:14      评论:0      收藏:0      [点我收藏+]

面向对象进阶


@property装饰器

不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效。我们之前的建议是将属性命名以单下划线开头,通过这种方式来暗示属性是受保护的,不建议外界直接访问,那么如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用@property包装器来包装getter和setter方法,使得对属性的访问既安全又方便
class Persion(object):


    def __init__(self, name, age):
         self._name = name
         self._age = age

    #访问器
    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    #修改器
    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print("%s正在玩飞行棋."%self._name)
        else:
            print(‘%s正在玩斗地主‘%self._name)


def main():
    person = Persion(‘wdc‘, 12)
    person.play()
    person.age = 22
    person.play()


if __name__ == ‘__main__‘:
    main()

__slots__

动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。
class Persion(object):

    __slots__= (‘_name‘, ‘_age‘, ‘_gender‘)
    def __init__(self, name, age):
         self._name = name
         self._age = age

    #访问器
    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    #修改器
    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print("%s正在玩飞行棋."%self._name)
        else:
            print(‘%s正在玩斗地主‘%self._name)


def main():
    person = Persion(‘wdc‘, 12)
    person.play()
    person.age = 22
    person.play()


if __name__ == ‘__main__‘:
    main()

静态方法和类方法

例如我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然就不是对象方法,因为在调用这个方法时三角形对象尚未创建出来(因为都不知道三条边能不能构成三角形),所以这个方法是属于三角形类而并不属于三角形对象的。我们可以使用静态方法来解决这类问题
from math import sqrt

class Triangle(object):


    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

    @staticmethod
    def is_valid(a, b, c):
        return a + b >c and a + c >b and b + c >a

    def perimeter(self):
        return self._a + self._b + self._c


    def area(self):
        half = self.perimeter() / 2
        return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))


def main():
    a, b, c = 3, 4, 5
    # 静态方法和类方法都是通过给类发消息来调用的
    if Triangle.is_valid(a, b, c):
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
        # print(Triangle.perimeter(t))
        print(t.area())
        # print(Triangle.area(t))
    else:
        print(‘无法构成三角形.‘)

if __name__ == ‘__main__‘:
    main()
和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象,
from time import clock, time, localtime, sleep


class Clock(object):
    """数字时钟"""

    def __init__(self, hour=0, minute=0, second=0):
        self._hour = hour
        self._minute = minute
        self._second = second

    @classmethod
    def now(cls):
        ctime = localtime(time())
        return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)

    def run(self):
        """RUN"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute = self._minute + 1

            if self._minute == 60:
                self._minute = 0
                self._hour = self._hour + 1

                if self._hour == 24:
                    self._hour =0

    def show(self):
        """显示时间-"""
        return  "%02d:%02d:%02d"  %(self._hour, self._minute, self._second)

def main():
    #通过类方法创建对象并获取时间
    clock = Clock.now()
    while True:
        print(clock.show())

        sleep(1)

        clock.run()

if __name__ == ‘__main__‘:
    main()

类之间的关系

简单的说,类和类之间的关系有三种:is-a、has-a和use-a关系。
	is-a关系也叫继承或泛化,比如学生和人的关系、手机和电子产品的关系都属于继承关系。
	has-a关系通常称之为关联,比如部门和员工的关系,汽车和引擎的关系都属于关联关系;关联关系如果是整体和部分的关联,那么我们称之为聚合关系;如果整体进一步负责了部分的生命周期(整体和部分是不可分割的,同时同在也同时消亡),那么这种就是最强的关联关系,我们称之为合成关系。
	use-a关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。

继承和多态

一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,在实际开发中,我们经常会用子类对象去替换掉一个父类对象,这是面向对象编程中一个常见的行为,对应的原则称之为里氏替换原则。
class Persion(object):
    """人"""


    def __init__(self, name, age):
        self._name = name
        self._age = age

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        print(‘%s正在愉快的玩耍‘ % self.name)

    def watch(self):
        if self.age >= 18:
            print(‘%s正在观看爱情片.‘ %self.name)
        else:
            print(‘%s正在观看动画片.‘ %self.name)

class student(Persion):
    """学生"""
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self._grade = grade

    @property
    def grade(self):
        return self._grade

    @grade.setter
    def grade(self, grade):
        self._grade = grade



    def study(self, course):
        self._course = course
        print(‘%s的%s正在学习%s‘ % (self.grade, self.name, self._course))

class Teacher(Persion):
    """老师"""
    def __init__(self, name, age, title):
        super().__init__(name, age)
        self._title = title

    @property
    def title(self):
        return self._title

    @title.setter
    def title(self, title):
        self._title = title
    
    def teach(self, course):
        print(‘%s%s正在讲%s.‘ % (self._name, self._title, course))

def main():
    stu = student(‘wxc‘, 14, ‘初三‘)
    stu.play()
    stu.watch()
    stu.study(‘Math‘)

    t = Teacher(‘fwm‘, 20, ‘教授‘)
    t.teach(‘Python程序设计‘)

if __name__ == ‘__main__‘:
    main()
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)
from abc import ABCMeta, abstractmethod


class Pet(object, metaclass=ABCMeta):
    """宠物"""

    def __init__(self, nickname):
        self._nickname = nickname

    @abstractmethod   #加上@abstractmethod装饰器后严格控制子类必须实现这个方法
    def make_voice(self):
        """发出声音"""
        pass


class Dog(Pet):
    """狗"""

    def make_voice(self):
        print(‘%s: 汪汪汪...‘ % self._nickname)


class Cat(Pet):
    """猫"""

    def make_voice(self):
        print(‘%s: 喵...喵...‘ % self._nickname)


def main():
    pets = [Dog(‘旺财‘), Cat(‘凯蒂‘), Dog(‘大黄‘)]
    for pet in pets:
        pet.make_voice()


if __name__ == ‘__main__‘:
    main()

"""
某公司有三种类型的员工 分别是部门经理、程序员和销售员
需要设计一个工资结算系统 根据提供的员工信息来计算月薪
部门经理的月薪是每月固定15000元
程序员的月薪按本月工作时间计算 每小时150元
销售员的月薪是1200元的底薪加上销售额5%的提成
"""

from abc import ABCMeta, abstractmethod


class Employee(object, metaclass=ABCMeta):
    """初始化"""
    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name


    @abstractmethod
    def get_salary(self):
        """薪资"""
        pass


class Manager(Employee):
    """部门经理"""
    def get_salary(self):
        return 15000.0


class Programmer(Employee):
    """程序员"""
    def __init__(self, name, hours=0):
        super().__init__(name)
        self._hours = hours

    
    @property
    def hours(self):
        return self._hours


    @hours.setter
    def hours(self, hours):
        self._hours = hours if hours > 0 else  0

    
    def get_salary(self):
        return 150.0 * self._hours



class Salesman(Employee):
    """销售员"""
    def __init__(self, name, sales=0):
        super().__init__(name)
        self._sales = sales 

    @property
    def sale(self):
        return self._sales


    @sale.setter
    def sale(self, sales):
        self._sales = sales  if sales > 0 else 0


    def get_salary(self):
        return self._sales * 0.05 + 1200.0


def main():
    emps = [
        Manager(‘LB‘), Programmer(‘Zgl‘),
        Manager(‘Cc‘), Salesman(‘Gy‘),
        Salesman(‘Zf‘), Programmer(‘X‘),
        Programmer(‘Zy‘)
    ]

    for emp in emps:
        if isinstance(emp, Programmer):
            emp.hours = int(input(‘请输入%s的工作的时间:‘ % emp.name))
        elif isinstance(emp, Salesman):
            emp.sale = int(input(‘请输入%s的销售总额:‘ % emp.name))

        print(‘%s 本月的工资为: %s¥‘ %(emp.name, emp.get_salary()))

if __name__ == ‘__main__‘:
    main()

Python面向对象进阶

原文:https://www.cnblogs.com/fangweiming/p/15038516.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!