python面向对象编程(封装隐藏)

Posted coderxueshan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python面向对象编程(封装隐藏)相关的知识,希望对你有一定的参考价值。

一 封装

1、封装介绍
封装是面向对象三大特性最核心的一个特性
封装《-----》整合

2、将封装的属性进行隐藏操作
1)、如何隐藏:在属性名前加__前缀,就会实现一个对外隐藏属性效果
该隐藏需要注意的问题:
(1)在类外部无法直接访问双下滑线开头的属性,但知道了类名和属性名就可以拼出名字:
所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。
class Foo:
    __x = 1  # _Foo__x

    def __f1(self):  # _Foo__f1
        print("test")
# Foo.__X
print(Foo.__dict__)
obj1 = Foo()
print(obj1._Foo__x)
obj1._Foo__f1()
(2)这种隐藏对外不对内,因为__开头的属性会在类定义阶段&检查语法时统一发生变形
class Foo:
    __x = 1  # _Foo__x

    def __f1(self):  # _Foo__f1
        print("test")

    def f2(self):
        print(self.__x)
        print(self.__f1)


print(Foo.__dict__)
obj2 = Foo()
obj2.f2()
(3)这种变形操作只在检查类体语法的时候发生一次,之后定义的__开头的属性都不会变形
class Foo:
    __x = 1  # _Foo__x

    def __f1(self):  # _Foo__f1
        print("test")

    def f2(self):
        print(self.__x)
        print(self.__f1)

Foo.__y=3
print(Foo.__dict__)
obj2 = Foo()
obj2.f2()
print(Foo.__y)
2)、为何要隐藏
(1)隐藏数据属性
将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,
接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
# 设计者:
class People:
    def __init__(self, name):
        self.__name = name

    def get_name(self):
        # 通过该接口就可以间接地访问到名字属性
        print(self.__name)

    def set_name__(self, val):  # 增加数据属性
        self.__name = val


# 使用者
obj = People(\'lq\')
print(obj.name) # 无法直接用名字属性
obj.get_name()
(2)隐藏函数/方法属性:目的是为了隔离复杂度
\'\'\'
例如ATM程序的取款功能,该功能有很多其他功能组成,比如插卡、身份认证、输入金额、打印小票、取钱等,
而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
\'\'\'

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()

二 property

# 装饰器是在不修改被装饰对象源代码以及调用方式的前提下为被装饰器对象添加
# 新功能的可调用对象
print(property) # <class \'property\'>

# property是一个装饰器,是用来绑定给对象的方法伪造成一个数据属性
# 案例一:
class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    # 定义函数的原因1:
    # 1、从bmi的公式上看,bmi应该是触发功能计算得到的
    # 2、bmi是随着身高、体重的变化而动态变化的,不是一个固定的值
    #     说白了,每次都是需要临时计算得到的

    # 但是bmi听起来更像是一个数据属性,而非功能
    @property
    def bmi(self):
        return self.weight / (self.height ** 2)


obj1 = People(\'lq\', 70, 1.63)
# print(obj1.bmi())
print(obj1.bmi)  # 本来是个功能,加了property后,调用不用加(),当成数据属性使用
print(obj1.name)
\'\'\'
26.346494034400994
lq
\'\'\'
# 案例二:
class People:
    def __init__(self, name):
        self.__name = name

    def get_name(self):  # obj1.name
        return self.__name

    def set_name(self, val):  # obj1.name=\'LQ\'
        if type(val) is not str:
            print(\'必须传入str类型\')
            return
        self.__name = val

    def del_name(self):  # del obj1.name
        print(\'不让删除\')

    name123 = property(get_name, set_name, del_name)


obj2 = People(\'zd\')
print(obj2.name123)
obj2.name123 = \'ZD\'
print(obj2.name123)
del obj2.name123
\'\'\'
zd
ZD
不让删除
\'\'\'
# 案例三:
class People:
    def __init__(self, name):
        self.__name = name

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

    @name.setter
    def name(self, val):  # obj1.name=\'LQ\'
        if type(val) is not str:
            print(\'必须传入str类型\')
            return
        self.__name = val

    @name.deleter
    def name(self):  # del obj1.name
        print(\'不让删除\')


obj3 = People(\'lq\')
print(obj3.name)
obj3.name = \'ZD\'
print(obj3.name)
del obj3.name
\'\'\'
lq
ZD
不让删除
\'\'\'

Python之面向对象

1》面向对象编程(Object-Oriented Programming):
  对于编程语言的初学者而言,OOP不是一个很容易理解的编程方式,OPP的三大特性有继承,封装,多态,OOP也使得我们对代码的修改和扩展变得更容易;
     封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行信息隐藏;
     继承:可以使用现有类的所有功能,并在无须重新编写原来的类的情况下对这些功能进行扩展;一般情况下,一个子类只能有一个基类,要实现多重继承,                        可以通过多级继承来实现;继承概念的实现方式有三类:实现继承,接口继承和可视继承;
      实现继承:使用基类的属性和方法而无需额外编码的能力;
      接口继承:仅使用属性和方法的名称,但是子类必须提供实现的能力;
      可视继承:子类使用基类的外观和实现代码的能力;
      OOP开发范式大致为: 划分对象->抽象类->将类组织成为层次化结构(继承和合成)->用类与实例进行设计和实现;
  多态:允许将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运行;简单的                    说,允许将子类类型的指针赋值给父类类型的指针;
  封装和继承是为了代码重用,而多态则是为了接口重用;
  把一个抽象的类变成一个具体的对象的过程叫实例化;                                          

            1>类和构造方法:

          技术分享

        2>类的变量与实例变量:

        技术分享

               技术分享

                                       技术分享

        3>类的继承:
        class SchoolMember(object):
            membur_nums = 0
        def __init__(self,name,age,sex):
          self.name = name
          self.age = age
          self.sex = sex
          self.enroll()
        def enroll(self):
          SchoolMember.membur_nums +=1
    # print("\\033[32:1m The [%s] memburs SchoolMember [%s] is enrolled!\\033[0m" %(self.membur_nums,self.name))
          
print("The [%s] memburs SchoolMember [%s] is enrolled!" % (self.membur_nums, self.name))
      def
tell(self):
            print(
"Hello my name is %s" %self.name)
      class
Teacher(SchoolMember):
      
def __init__(self,name,age,sex,course,salary):
        super(Teacher,
self).__init__(name,age,sex)
        
self.course = course
        
self.salary = salary
      
def teaching(self):
        print(
"Teacher [%s] is teaching [%s]" %(self.name,self.course))
      class
Student(SchoolMember):
      
def __init__(self,name,age,sex,course,tuition):
        super(Student,
self).__init__(name,age,sex)
        
self.course = course
        
self.tuition = tuition
      
def pay_tuition(self):
        print(
"cao,student [%s] paying tuition [%s]" %(self.name,self.tuition))
       t1 = Teacher(
"Alex",22,‘F‘,"PY",1000)
     t2 = Teacher(
"Tenglan",25,‘N/A‘,"PY",900)

     s1 = Student(
"SanJiang",24,"Female","python",15000)
     s2 = Student(
"BaoAn",23,"F","python",5000)

       t1.tell()
       t1.teaching()
       s1.tell()
       s1.pay_tuition()

                        技术分享

     4>类的静态方法类方法及属性:
      ****python不支持多态并且也用不到多态,多态用于java和c#中;
      多态的应用: 

        技术分享 

        技术分享

           类的成员可以分为三大类:字段,方法和属性;

          技术分享

      1)字段:字段包括普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,普通字段属于对象,静态                                字段属于类,普通字段需要通过对象来访问,静态字段通过类访问;
      静态字段在内存中只保存一份,普通字段在每个对象中都要保存一份;
      静态字段===类变量,普通字段====实例变量;
    2)属性(类方法):其中的装饰器将方法变为类方法,只能通过类来调用,实例不可以直接调用;
      属性的基本使用:  

                            技术分享

                            技术分享

                         类的静态方法:不能访问类变量,也不能访问实例变量;

          技术分享

                            类的属性,将方法变为属性:

          技术分享

                          给属性设置值:

          技术分享

           技术分享

            删除属性的设置值:

          技术分享

       4>新式类和经典类:
      1)多继承:新式类用广度优先查找,经典类用深度优先查找(3.0中都是广度优先);        

          技术分享

                      2)类的描述信息:__doc__; 

          技术分享

        3)类中实例销毁:__del__(析构函数),一直将程序执行完之后会执行实例销毁;

         技术分享

        技术分享

        4)__dict__ 以字典形式遍历出类下的所有变量;

         技术分享

         5>反射的妙用:

        import sys
        class WebServer(object):
          def __init__(self,host,port):
            self.host = host
            self.port = port

          def start(self):
            print("Server is starting...")
          def
stop(self):
            print("Server is stopping...")
          def
restart(self):
            self.stop()
            self.start()

        def test_run(self,name):
          print("running...",name,self.host)

      if
__name__ =="__main__":
        server = WebServer(
‘localhost‘,333)
        
#print(sys.argv[1])
        
if hasattr(server,sys.argv[1]):
          func = getattr(server,sys.argv[
1]) #获取server.start内存地址
          
func() #server.start()
        # setattr(server,"run",test_run) #类的实例,属性,方法名
        # server.run(server,"che")

        # delattr(server,"host") #删除实例中的对象
        # print(server.host)

        
delattr(WebServer,"start") #删除类中的方法
          
print(server.restart())
        
# cmd_dic = {
            # "start":server.start,
            # "stop":server.stop,
            # "restart":server.restart,
            # }
      #if sys.argv[1] == "start":
      # if sys.argv[1] in cmd_dic:
      # cmd_dic[sys.argv[1]]()
 

                     技术分享





























































































以上是关于python面向对象编程(封装隐藏)的主要内容,如果未能解决你的问题,请参考以下文章

python学习笔记DAY16(面向对象编程)

Python面向对象编程第08篇 私有变量

Python面向对象编程第08篇 私有变量

Python面向对象编程

python面向对象编程 -- 封装继承(python3.5)

面向对象之封装