Python学习之面向对象进阶

面向对象进阶当然是要谈谈面向对象的三大特性:封装、继承、多态

@property装饰器

python虽然不建议把属性和方法都设为私有的,但是完全暴露给外界也不好,这样,我们给属性赋值的有效性九无法保证,因此,为了使得对属性的访问既安全又方便,可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作,在python中,可以考虑使用@property包装器来包装getter和setter方法

class Person(object):
    def __init__(self,name,age):
        self._name=name
        self._age=age
    #访问器 - getter方法
    @property
    def name(self):
        return self._name
    @property
    def age(self):
        return self._age
    # 修改器 - setter方法
    @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=Person("wangbb",16)
    person.play()
    #调用setter修改器修改其属性
    person.age=21
    person.play()
    #person.name=‘wbb‘  #AttributeError: can‘t set attribute
if __name__==‘__main__‘:
    main()

效果入下图:

__slots__魔法

__slots__魔法是为了让python这个动态语言,限定我们的自定义类型只能绑定特定的属性,而且只对当前类生效,对其子类没有限制作用

class Person(object):
    # 限定Person类只能绑定_name,_age,_gender属性,
    # 此处请注意,_name和name不是同一种属性,不能绑定name属性
    __slots__ = (‘_name‘,‘_age‘,‘_gender‘)
    # Person类初始化
    def __init__(self,name,age):
        self._name=name
        self._age=age
    #访问器 - getter方法
    @property
    def name(self):
        return self._name
    @property
    def age(self):
        return self._age
    # 修改器 - setter方法
    @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=Person("wangbb",16)
    person.play()
    #调用setter修改器修改其属性
    person.age=21
    person.play()
    person._gender=‘男‘
    #person._isgay=True AttributeError: ‘Person‘ object has no attribute ‘_isgay‘

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):
        href=self.perimeter()/2
        return sqrt(href*(href-self._a)*(href-self._b)*(href-self._c))
def main():
    a,b,c=3,4,5
    #静态方法和类方法都是通过给类发消息来调用的
    if Triangle.is_valid(a,b,c):
        triangle=Triangle(a,b,c)
        print("三角形的周长是:",triangle.perimeter())
        # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
        print(Triangle.perimeter(triangle))
        print("三角形的面积是:",triangle.area())
        print(Triangle.area(triangle))
    else:
        print("不好意思,不能构成三角形!")
if __name__==‘__main__‘:
    main()

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

from time import 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):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                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关系通常称之为依赖,比如司机有一个驾驶的行为(方法),其中(的参数)使用到了汽车,那么司机和汽车的关系就是依赖关系。

继承和多态

python可以在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也叫超类或基类;得到继承信息的我们称之为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力,子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。

Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。

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 manger(employee):
    def get_salary(self):
        return 15000.0
class programer(employee):
    def __init__(self,name,work_hour=0):
        super().__init__(name)
        self._work_hour=work_hour
    def get_salary(self):
        return 150.0*self._work_hour
    @property
    def work_hour(self):
        return self._work_hour
    @work_hour.setter
    def work_hour(self,work_hour):
        self._work_hour=work_hour if work_hour>0 else 0
class salesman(employee):
    def __init__(self,name,sales=0):
        super().__init__(name)
        self._sales=sales
    def get_salary(self):
        return 1200.0+self._sales*0.05
    @property
    def sales(self):
        return self._sales
    @sales.setter
    def sales(self,sales):
        self._sales=sales if sales >0 else 0
def main():
    emps=[manger(‘wbb‘),programer(‘bb‘),salesman(‘lj‘)]
    for emp in emps:
        if isinstance(emp,programer):
            emp.work_hour=int(input("请输入%s本月工作时长:"%emp.name))
        elif isinstance(emp,salesman):
            emp.sales=float(input("请输入%s本月的销售量:"%emp.name))
        print("%s本月的工资为:¥%s元"%(emp.name,emp.get_salary()))
if __name__==‘__main__‘:
    main()

原文地址:https://www.cnblogs.com/baobao2201128470/p/11291736.html

时间: 2024-10-13 00:28:38

Python学习之面向对象进阶的相关文章

python学习总结(面向对象进阶)

-------------------类属性和实例属性关系------------------- 1.类属性和实例属性关系 1.实例属性 实例对象独有的属性 2.类属性 类名访问类属性 3.实例中无同名属性时,可访问到类属性,当定义同名实例属性时,则无法访问 4.常用的查找指令 1.vars :查看实例内属性 2.dir :显示类属性和所有实例属性 3.type :显示类型 -------------------方法------------------- 1.实例方法 隐含的参数为类实例self

python学习_day28_面向对象进阶

一.内置函数isinstance和issubclass 1.isinstance() isinstance(obj,cls)检查obj是否是类 cls 的对象,类似type(). class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) #输出结果:True print(isinstance(10,int)) #输出结果:True sinstance() 与 type() 区别:type() 不会认为子类是一种父类类型,不考虑

Python学习笔记-面向对象进阶(一)封装、多态、继承

一.初识继承 1.什么是继承? 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类.子类会"遗传"父类的属性,从而解决代码重用问题. # python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1

Python学习笔记-面向对象进阶(二)

一.反射 1.什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省). 2.Python面向对象中的反射 通过字符串的形式操作对象相关的属性.python中的一切事物都是对象(都可以使用反射) 3.四个可以实现自省的函数 (1)hasattr(object,name),判断object中有没有一个name字符串对应的方法或属性,检测是否含有某属性. class BlackMedium: feture='Ugly' def _

python学习之面向对象高级特性

类属性与实例属性类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本.在前面的例子中我们接触到的就是实例属性(对象属性),它不被所有类对象的实例对象所共有,在内存中的副本个数取决于对象个数. 05_类属性鱼实例属性.py import random class Turtle(object): # power是类属性. power = 100 def __init__(self): # x,y:实例属性. self.x = random.randint(0, 10)

Python学习笔记-面向对象

一.什么是面向对象的程序设计 1.面向过程的程序设计 面向过程:核心是过程二字,过程即解决问题的步骤,就是先干什么,再干什么.基于该思想写程序就好比在设计一条流水线,是一种机械式的思维方式. 优点:复杂的过程流程化,进而简单化 缺点:扩展性差 2.面向对象的程序设计 面向对象:核心是对象二字,对象是特征与技能的结合体.基于该思想编写程序就好比在创造一个世界,世界是由一个个对象组成,是一种"上帝式"的思维方式 优点:可扩展性强 缺点:编程复杂度高,容易出现过度设计问题 二.类与对象 对象

学习PYTHON之路, DAY 8 - PYTHON 基础 8 (面向对象进阶)

类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 字段定义和使用 由上述代码可以看出[普通字段需要通过对象来访问][静态字段通过类访问],在使用上可以看出普通字段和静态字段的归属是

python学习之面向对象学习进阶

一.property属性高级用法 可以将对象方法作为属性使用 例子: class Foo:     def __init__(self, age):         )        self.__age = age     @property     def age(self):         return self.__age     @age.setter     def age(self, args):         self.__age = args     @age.delete

python自动化开发学习-8 面向对象进阶

---恢复内容开始--- 类的成员(字段,方法,属性) 注意:所有成员中,只有普通字段的内容是保存在对象中.而其他成员都是保存在类中,即无论创建多少个对象,在内存中只保留一份. 1.字段 字段包含:普通字段和静态字段,在使用中有所区别,最本质的区别是内存中保存的位置不同. 普通字段:属于对象 静态字段:属于类, 多个对象共用一个字段,主要用于对象的变量内容都一样的情景. 注意: 静态字段在代码加载的时候就被创建了,而普通字段在类被实例化的时候才会被创建.# 示例代码: class Provinc