15-面向对象进阶

面向对象

三个特征

封装

没有学习封装之前,效果如下:

class Person(object):

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

xiaoming = Person("alvin",16)

xiaoming.age = 1000
print(xiaoming.age)
xiaoming.age = -10
print(xiaoming.age)
# 可以看到,外界可以随意修改数据,并可能把数据设置成一个不合理的脏数据。

所谓的封装,就是对类中成员属性和方法进行保护,设置对应的访问权限控制外界对类的内部成员的访问,修改,删除等操作,有条件的开放外界对数据的操作。

访问权限

常见的编程语言中对于类或对象的成员保护与访问机制,分3个等级:

访问权限 描述 格式
私有的
(private)
只能在当前类内部可以访问与操作,类的外部不可以。 __方法名
__属性名
公有的
(public)
在当前类内部和外部都可以访问操作。 方法名
属性名
受保护的
(protected)
在当前类内部和子类内部可以访问,外界无法访问。
python原生不支持,但是python开发者都约定俗成了左边单个下划线开头属于受保护的
_方法名()
_属性名

Python对成员的保护只有两个等级:私有的(private)和公有的(public)。在java,php,c++等编程语言里面就存在3种等级。

import re

class Person(object):
    def __init__(self, name):
        self.__name = name

    def get_name(self):
        return self.__name

    def set_name(self, name):
        if self.__check_name(name):
            self.__name = name
        else:
            raise Exception("名字长度不能大于7个字符!")

    def __check_name(self, name):
        return len(re.split("", name)[1:-1]) < 5

xiaoming = Person("小明")
# print(xiaoming.__name) # 报错!
xiaoming.set_name("小红")
# xiaoming.__check_name("小红") # 报错!
print(xiaoming.get_name())
xiaoming.set_name("小红五一到此一游") # 报错!

所以,所谓的封装其实就是为了让一些属性和方法,不能被外界直接修改和调用而已。对数据的修改,可以通过提供公有方法的方式给外界操作,那么外界操作时,我们就可以设置一些判断了。而判断名字这种方法,外界没有必要使用到,所以我们可以设置为私有级别,这样,对于外界来说,就不存在这个判断名字的方法了。

注意:类中不仅可以把实例属性和实例方法设置私有的或公有的,类的类属性和类方法也可以这么设置,只是很少有人这么用而已,因此我们这里不作介绍。

属性封装

使用接口函数获取修改数据 和 使用赋值设置数据相比, 赋值设置数据使用起来更方便,我们有什么方法达到 既能使用赋值方式,同时又能在赋值时直接调用到我们定义的方法接口对数据校验呢?有的,答案就是@property(属性装饰器)。

class Student(object):
    def __init__(self, name, age):
        self.__name = name
        self.__sex = sex

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

    @name.setter
    def name(self,name):
        if len(name) > 1 :
            self.__name = name
        else:
            print("name的长度必须要大于1个长度")

注意,使用 @property 装饰器时,接口名不必与属性名相同。

python还提供了更加人性化的操作,可以通过property函数限制方式完成只读、只写、读写、删除等各种操作

class Person(object):
    def __init__(self, name):
        self.__name = name

    def __get_name(self):
        return self.__name

    def __set_name(self, name):
        self.__name = name

    def __del_name(self):
        del self.__name
    # property()中定义了读取、赋值、删除的操作
    # name = property(__get_name, __set_name, __del_name)
    name = property(__get_name, __set_name)

xiaoming = Person("xiaoming")

print(xiaoming.name)    # 合法:调用__get_name
xiaoming.name = "小明"  # 合法:调用__set_name
print(xiaoming.name)

# property中没有添加__del_name函数,所以不能删除指定的属性
del xiaoming.name  # 错误:AttributeError: can't delete Attribute

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

继承

面向对象的编程带来的主要好处之一是复用代码,实现复用代码的方法之一是通过类的继承机制。

基本使用

通过继承创建的新类称为子类派生类后代类,被继承的类称为基类父类超类

class 子类名(父类名):
    pass

继承是使用已有父类作为基础创建子类的一种方式。子类的定义可以增加新的属性或方法,也可以复用或覆盖父类已有的属性和方法。

注意:其他的语言,是可以选择性的复用父类属性和方法,而python中默认是全局复用的。

使用继承之前:

class Student(object):
    """学生类"""
    def __init__(self, name, age, achievement):
        self.name=name
        self.age=age
        self.achievement = achievement

    def eat(self):
        print("eating...")

    def sleep(self):
        print("sleep...")

    def do_homework(self):
        print("do_homework.....")

    def do_read(self):
        print("reading........")

class Teacher(object):
    """老师类"""
    def __init__(self, name, age, salary):
        self.name=name
        self.age=age
        self.salary = salary

    def eat(self):
        print("eating...")

    def sleep(self):
        print("sleep...")

    def teaching(self):
        print("teaching.....")

使用继承以后:

class Person(object):
    """人类"""
    def eat(self):
        print("eating...")

    def sleep(self):
        print("sleep...")

class Student(object):
    """学生类"""
    def __init__(self, name, age, achievement):
        self

你可能感兴趣的:(Python,python,开发语言)