python之面向对象三大特性——封装

1、封装
1.1、定义
1、封装就是把数据与功能都整合到一起,“整合”二字其实就是封装的通俗说法
2、在封装的基础上,我们可以将装到对象或者类中的属性给隐藏起来
注意:
	(1) 在定义类或者初始化对象时,在属性前加__,就会将该属性隐藏起来
        但该隐藏起始只是一种变形_类名__属性名,并没有真的隐藏起来

    (2) 该变形操作是在类定义阶段扫描语法时发生的变形,类定义之后添加的__开头的属性不会发生变形

    (3) 该隐藏是对外不对内

    (4) 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
1.2、使用
class Student:
    __school = 'ml'  # 隐藏属性 _Student__school

    def __init__(self, name, age, gender):
        self.name = name
        self.__age = age  # _Student__age
        self.gender = gender

    # 相同的功能
    def choose(self):
        print('{}正在选课'.format(self.name))

stu_obj = Student('allen', 18, 'male')

# 隐藏属性其实也是保存在字典中,只不过存储的属性名字变形了,变成了_类名__属性名
print(stu_obj.__dict__)  # {'name': 'allen', '_Student__age': 18, 'gender': 'male'}
print(stu_obj._Student__school)  # ml
print(stu_obj._Student__age)  # 18

# 类定义之后添加的__开头的属性不会发生变形
stu_obj.__xxx = 111
print(stu_obj.__dict__)  # {'name': 'allen', '_Student__age': 18, 'gender': 'male', '__xxx': 111}
1.3、隐藏属性的意义
1.3.1、对外提供数据接口
# 把数据属性隐藏起来的意义是: 在类内开放接口,让外界使用者通过接口来操作属性值,我们可以在接口之上附加任意的逻辑,来严格控制外界使用者对属性的操作

class Student:

    def __init__(self, name, age, gender):
        self.name = name
        self.__age = age  # _Student__age
        self.gender = gender

    # 对外提供接口访问年龄属性
    def get_age(self):
        return self.__age  # 隐藏属性对外不对内

    def set_age(self, value):
        # 我们可以在接口之上附加任意的逻辑,来严格控制外界使用者对属性的操作
        if not isinstance(value, int):
            print('年龄必须是正整数')
            return
        self.__age = value

    def del_age(self):
        print('不允许删除')

stu_obj = Student('allen', 18, 'male')
print(stu_obj.age)  # 报错 没有该属性
print(stu_obj.__age)  # 报错 没有该属性
print(stu_obj.get_age())  # 18

stu_obj.set_age('aaa')  # 为age添加属性类型是字符串 接口返回: 年龄必须是正整数
print(stu_obj._Student__age)  # age属性没有修改成功,仍然是18
stu_obj.set_age(19)  # 接口中逻辑检测通过,年龄修改成功
print(stu_obj._Student__age)  # 19
stu_obj.del_age()  # 不允许删除
1.3.2、把功能属性隐藏起来:隔离复杂度
# 将类中不希望直接给用户访问的属性和方法定义为隐藏属性,对外提供接口给用户访问

class ATM:
    def __card(self):
        print('插卡')

    def __auth(self):
        print('用户认证')

    def __input(self):
        print('输入取款金额')

    def __print_bill(self):
        print('打印账单')

    def __take_money(self):
        print('取款')

    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()

obj = ATM()
obj.withdraw()
1.4、property
# python专门提供了一个装饰器property,可以将类中的函数“伪装成”对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果
# 使用property有效地保证了属性访问的一致性

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

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)

p_obj = Person('allen', 1.82, 68)
print(p_obj.bmi)  # 使用property装饰后访问方法直接可以使用点属性的方法访问

针对property提供获取、设置和删除属性的功能

1.4.1、方式一
class Student:

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

    def get_age(self):
        return self.__age

    def set_age(self, value):
        self.__age = value

    def del_age(self):
        print('不可以删除')

    age = property(get_age, set_age, del_age)

stu_obj = Student('allen', 18, 'male')
# 获取属性
print(stu_obj.age)  # 18
# 修改属性
stu_obj.age = 19
print(stu_obj.age)  # 19
# 删除属性
del stu_obj.age  # 不可以删除
print(stu_obj.age)  # 19
1.4.2、方式二
class Student:

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

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

    @age.setter
    def age(self, value):
        self.__age = value

    @age.deleter
    def age(self):
        print('不可以删除')

stu_obj = Student('allen', 18, 'male')
# 获取属性
print(stu_obj.age)  # 18
# 修改属性
stu_obj.age = 19
print(stu_obj.age)  # 19
# 删除属性
del stu_obj.age  # 不可以删除
print(stu_obj.age)  # 19
1.5、绑定方法
1.5.1、定义
======类中的定义的函数======
绑定方法: 谁来调用就会将谁当作第一个参数传入
(1)绑定给对象的方法: 类中定义的函数默认就是绑定给对象的方法,应该是由对象调用,会把对象当作第一个参数传入
(2)绑定给类的方法: 在类中的函数上加一个装饰器@classmethod,该函数就绑定给类了,应该是由类来调用,会把类当作第一个参数传入
1.5.2、绑定方法的使用
class Student:

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

    # 绑定给对象的方法
    def choose(self):
        print('{}正在选课'.format(self.name))
	
    # 绑定给类的方法
    @classmethod
    def f1(cls):
        print(cls)  # 哪个类来调用该方法就打印哪个类

stu_obj = Student('allen', 18, 'male')
stu_obj.choose()  # allen正在选课
Student.f1()  # <class '__main__.Student'>

# 用对象调用绑定给类的方法得到的还是对象所在的类
stu_obj.f1()  # <class '__main__.Student'>
1.6、非绑定方法
1.6.1、定义
======类中的定义的函数======
非绑定方法: 既不与类绑定也不与对象绑定,就是一个普通的函数,谁都可以来调用,没有自动传参的效果,在函数上添加装饰器@staticmethod
1.6.2、非绑定方法的使用
class Student:

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
	
    # 非绑定方法,类可以调用,对象也可以调用,没有自动传参的效果
    @staticmethod
    def f2(x, y):
        print(x, y)

stu_obj = Student('allen', 18, 'male')

print(Student.f2)  # <function Student.f2 at 0x00000274369DB4C0>
print(stu_obj.f2)  # <function Student.f2 at 0x00000274369DB4C0>
Student.f2(1, 2)  # 1 2
stu_obj.f2(1, 2)  # 1 2
1.7、绑定方法与非绑定方法综合案例
# 获取MySQL的主机与端口号
import uuid

class MySQL:
    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._uid = self.__create_uid()

    def check_detail(self):
        return '主机名: {}  端口: {}  id号: {}'.format(self._host, self._port, self._uid)

    # 该方法用不到对象也用不到类,定义为静态方法
    @staticmethod
    def __create_uid():
        return uuid.uuid4()

    @classmethod
    def from_conf(cls):
        import settings
        return cls(settings.host, settings.port)  # 在类方法中完成实例化

# 调用方式一: 实例化类给出参数
obj = MySQL('127.0.0.1', 3306)
print(obj.check_detail())  # 主机名: 127.0.0.1  端口: 3306  id号: d7785e10-c0cf-4d0b-a89a-8979d2f26c4b

# 调用方式二: 调用类方法,在类方法中实例化
cls_obj = MySQL.from_conf()
print(cls_obj.check_detail())  # 主机名: 127.0.0.1  端口: 3306  id号: e490e7e8-bbb7-4585-ad59-cea8b5f89f5c


# settings模块
host = '127.0.0.1'
port = 3306
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值