Python-封装

今日内容:(封装)

【封装】

  隐藏对象的属性和实现细节,仅对外提供公共访问方式。

【好处】

  1、将变隔离;

  2、便于使用;

  3、提高复用性;

  4、提高安全性;

【封装原则】

  1、将不需要对外提供的内容都隐藏起来;

  2、把属性都隐藏,提供公共方法对其访问。

私有变量和私有方法

在python中用双下划线开头的方式将属性隐藏起来

私有变量

#其实这仅仅这是一种变形操作
#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

class A:
    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X=10 #变形为self._A__X
    def __foo(self): #变形为_A__foo
        print('from A')
    def bar(self):
        self.__foo() #只有在类内部才可以通过__foo的形式访问到.

#A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

这种自动变形的特点:

1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果

2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

 

这种变形需要注意的问题是:

1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

2.变形的过程只在类的定义是发生一次,在定义后的赋值操作,不会变形

 

私有方法

  1、有些方法的返回值只是用来作为中间结果

  2、父类的方法不希望子类继承      

 

class Foo:
    def __jinghong_sb(self):     #_Foo__jinghong_sb
        print('Foo')

class Son(Foo):
    def __jinghong_sb(self):
        print('Son')

    def func(self):
        self.__jinghong_sb()     #_Son__jinghong_sb

son = Son()
son.func()

 

 

#封装
class Teacher:
    __identifier = 'Teacher'   #私有静态属性
    def __init__(self,name,pwd):
        self.name = name
        self.__pwd = pwd     #私有属性
        self.__p()

    def __p(self):          #私有方法
        return hash(self.__pwd)

    def login(self,password):
        #self.__pwd == password
        return hash(password) == self.__p()
# print(Teacher._Teacher__identifier) 
alex = Teacher('alex','3714')
ret = alex.login('3714')
print(ret)
# print(alex._Teacher__b)
# print(alex.__dict__)
View Code

 

 

私有属性

实例1:

# 例一: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 Person:
    def __init__(self,name,height,weight):
        self.name = name
        self.__height = height
        self.__weight = weight

    def get_bmi(self):
        return self.__weight / (self.__height*self.__height)

    def change_weight(self,new_weight):
        if new_weight > 20:
            self.__weight = new_weight
        else:
            print('体重过轻')
jinghong = Person('景弘',1.81,94)
print(jinghong.get_bmi())
View Code

实例2:

#房屋 :
#  业主 长 宽
#  面积
class Host:
    def __init__(self,owner,length,width):
        self.owner = owner
        self.__length = length
        self.__width = width

    def area(self):
        return self.__length * self.__width

zangsan = Host('张三',10,20)
print(zhangsan.area())

property属性

property是一种特殊属性,访问它时会执行一段功能(函数)然后返回值

 例一
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**2)

p1=People('egon',75,1.85)
print(p1.bmi)
View Code

为什么要用property

将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方法遵循了统一访问的原则

除此之外,看下

ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

class Shop:
      discount = 0.75
      def __init__(self,name,price):
            self.name = name
            self.__price = price

      @property
      def price(self):
            return self.__price * Shop.discount

      @price.setter
      def price(self,new_price):
            self.__price = new_price
apple = Shop('apple',5)
print(apple.price)
apple.price = 6
print(apple.price)
View Code

 

classmethod

class Classmethod_Demo():
    role = 'dog'

    @classmethod
    def func(cls):
        print(cls.role)


Classmethod_Demo.func()

staticmethod

class Staticmethod_Demo():
    role = 'dog'

    @staticmethod
    def func():
        print("当普通方法用")

Staticmethod_Demo.func()

 

posted @ 2017-09-20 16:17  程先生_Python  阅读(117)  评论(0)    收藏  举报