面向对象之封装

一.引子

封装不等同于隐藏。

二.隐藏

2.1如何把属性隐藏起来?

就在属性前面加上__开头(注意不要加__结尾)
class Foo:
    x=111
    def __init__(self,y):
        self.__y=y#属性前加__

    def __f1(self):
        print('Foo,f1')

obj=Foo(2222)

print(obj.y)#'Foo' object has no attribute 'y'
print(Foo.x)

2.2加上__开头到底发生了什么事情,从而访问不到属性

python中的隐藏其实是一种语法的变形

class Foo:
    __x=1111
    def __init__(self,y):
        self.__y=y#属性前加__

    def __f1(self):
        print('Foo,f1')

obj=Foo(2222)

print(Foo.__dict__)#查看类的结构

print(obj._Foo__x)#查看出隐藏的属性
print(obj._Foo__y)
# 注意:
#1、其实这种隐藏只是一种语法上的变形,对外不对内
# 为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名

 

三.封装不是单纯意义上的隐藏

3.1什么是封装

装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来
强调:封装单从字面意思去看等同于隐藏,但其实封装绝对不是单纯意义的隐藏

 

 

pass

1.11什么是封装

装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来
强调:封装单从字面意思去看等同于隐藏,但其实封装绝对不是单纯意义的隐藏

1.12为什么要用封装

'''
#1 封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是
# 我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作
# class People:
#     def __init__(self,name,age):
#         self.__name=name
#         self.__age=age
#
#     def tell_info(self):
#         # u=input('user>>: ').strip()
#         # p=input('pwd>>: ').strip()
#         # if u == 'egon' and p == '123':
#             print(self.__name,self.__age)
#
#     def set_info(self,name,age):
#         if type(name) is not str:
#             raise TypeError('用户名必须为str类型')
#         if type(age) is not int:
#             raise TypeError('年龄必须为int类型')
#         self.__name=name
#         self.__age=age
#
# p=People('egon',18)
#
# # p.tell_info()
# # p.tell_info()
#
# # p.set_info('EGON',19)
# # p.tell_info()
#
# # p.set_info(353535353535353535,20)
# p.set_info('EGON','20')

#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.13如何用封装

# 如何把属性隐藏起来,就在属性前面加上__开头(注意不要加__结尾)
# 注意:
#1、其实这种隐藏只是一种语法上的变形,对外不对内
# 为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名

class Foo:
    __x=1111 #_Foo__x=1111
    def __init__(self,y):
        self.__y=y #self._Foo__y=y

    def __f1(self): #_Foo__f1
        print('Foo.f1')

    def get_y(self):
        print(self.__y) # print(self._Foo__y)

obj=Foo(22222)
# print(obj.x)
# print(obj.__x)
# obj.__f1()
# print(obj.y)
# print(obj.__y)
# print(Foo.__dict__)
# print(obj._Foo__x)
# print(obj._Foo__y)
# obj._Foo__f1()

# obj.get_y()

#2、这种语法意义上变形,只在类定义阶段发生一次,类定义之后,新增的__开头的属性都没有变形的效果

# Foo.__aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=1
# print(Foo.__dict__)

# obj.__bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb=2
# print(obj.__dict__)

#3、如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头
class Foo:
    def __f1(self): #_Foo__f1
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1() #obj._Foo__f1()

class Bar(Foo):
    def __f1(self): #_Bar__f1
        print("Bar.f1")

obj=Bar()

obj.f2()

 2.1封装之property

property实际应用

'''
BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
  体质指数(BMI)=体重(kg)÷身高^2(m)
  EX:70kg÷(1.75×1.75)=22.86

'''
class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
    def bmi(self):
        return self.weight/(self.height*self.height)


# 首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能
#都会立即计算一个值
egon=People('egon',75,1.80)
yl=People('yangli',85,1.74)

# 但很明显人的bmi值听起来更像一个名词而非动词
print(egon.bmi())
print(yl.bmi())
方式一(利用函数属性)
class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
     @property
    def bmi(self):
        return self.weight/(self.height*self.height)


# 首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能
#都会立即计算一个值
egon=People('egon',75,1.80)
yl=People('yangli',85,1.74)

# 但很明显人的bmi值听起来更像一个名词而非动词
print(egon.bmi)
print(yl.bmi)
方法二(将动词转成名词)

 property的增删改查

# 了解

# egon.bmi=123 # egon.bmi背后对应的是一个函数,所以不能赋值
class People:
    def __init__(self,name):
        self.__name=name

    @property
    def name(self): #obj.name
        print('您现在访问的是用户名。。。')
        return self.__name

    @name.setter #obj.name='EGON'
    def name(self,x):
        # print('=================',x)
        if type(x) is not str:
            raise TypeError('名字必须是str类型,傻叉')
        self.__name=x

    @name.deleter
    def name(self):
        # print('就不让你删')
        del self.__name

obj=People('egon')
#增删改查
# print(obj.name)
# print(obj.name())

# print(obj.name)

# obj.name='EGON'

# print(obj.name)

# obj.name=123

del obj.name
obj.name
posted @ 2018-12-28 20:55  王苗鲁  阅读(95)  评论(0编辑  收藏  举报