Python高级语法2:私有化、import、封装继承多态

简介: Python高级语法2:私有化、import、封装继承多态

一、私有化



  • xx : 公有变量
  • _x :单前置下划线,私有化属性或方法,from somemodule import * 禁止导入,类对象和子类可以访问
  • __xx: 双前置下划线,避免与子类中的属性命名冲突,无法外部直接访问(名字重整所以访问不到)
  • __xx__: 双前后下划线,用户名字空间的魔法对象或属性。例如: __init__,__不要自己发明这样的名字
  • xx_: 单后置下划线,用于避免与 Python 关键字的冲突

通过 name mangling (名字重整(目的就是防子类以重写基类的方法或者属性)如:_Class__object)机制就可以访问 private

class Person(object):
    def __init__(self,name,age,taste):
         self.name = name
         self._age = age
         self.__taste = taste
    def showperson(self):
        print(self.name)
        print(self._age)
        print(self.__taste)
    def dowork(self):
        self._work()
    def _work(self):
        print("my _work")
    def __away(self):
        print("my __away")
class Student(Person):
    def construction(self,name,age,taste):
        self.name = name
        self._age = age
        self.__taste = taste
    def showstudent(self):
        print(self._age)
        print(self.name)
        print(self.__taste)
    @staticmethod
    def testbug():
        _Bug.showbug()
class _Bug(object):
     @staticmethod
     def showbug():
        print("showbug")
s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)
# 无法访问__taste,导致报错
# s1.showstudent()
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)
s1.showstudent()
print('*'*20)
Student.testbug()


  • 总结
  • 父类中属性名为 __名字 的,子类不继承,子类不能访问
  • 如果在子类中向 __名字 赋值,那么会在子类中定义的一个与父类相同名字的属性


  • _名 的变量、函数、类在使用 from xxx import * 时都不会被导入


二、import 导入模块


  • 2.1、常见的导入方式


from xxx import yyy
import xxx
from xxx import *
import xxx,yyy
from xxx import zzz,nnn
import xxx as bbb
  • 2.2、import xxx as bbb 给模块起别名
  • 给模块起别名的好处:(1)、可以简化模块名太长的问题;(2)、解决引用的模块有和模块名一样的变量名
  • 举个例子:如果你导入一个模块aa,模块里面有一个属性 name,你在当前的模块又定义了一个变量aa,那么你再调用模块aa的name赋值的时候就会报错


import aa
aa = 100
aa.name = "Jack"
  • 运行结果:AttributeError: 'int' object has no attribute 'name'
    如果我们给aa模块起个别名bb,如:import aa as bb 就不会报错了


import aa as bb
aa = 100
bb.name = "Jack"
  • 2.3、import 搜索路径


import sys
print(sys.path)


image.png

  • 路径搜索
  • 从上面列出的目录里依次查找要导入的模块文件
  • '' 表示当前路径
  • 列表中的路径的先后顺序代表了python解释器在搜索模块时的先后顺序
  • 程序执行时添加新的模块路径


sys.path.append('/home/itcast/xxx')
sys.path.insert(0, '/home/itcast/xxx')  # 可以确保先搜索这个路径


image.png

  • .4、重新导入模块
    模块被导入后,import module不能重新导入模块,重新导入需用reload,也就是当你在一个模块内导入了一个 import module,接不管i导入多少次 import module都不起作用,只有第一句导入有效


三、多个模块 import 导入注意点(也就是公共模块的问题)



  • 3.1、我们定义4个模块:mainTest1Test2Common
  • Common 模块里面定义一个变量 HANDLE,初始值 FALSE


HANDLE = FALSE
  • Test1 模块


from Common import HANDLE
def change1():
      HANDLE = True
      if HANDLE:
            print("在 Test 里面修改HANDLE为:True")
      else:
            print("在 Test 里面没有修改HANDLE的值")
      print("*"*20)
  • Test2 模块


from Common import HANDLE
def change2():
     print(HANDLE)
     if HANDLE:
          print("在Test2里面 HANDLE 变为 True")
     else:
           print("在Test2里面 HANDLE 变为 False")
     print("*" * 20)
  • main 模块


import Common
import Test1
import Test2
if __name__ == "__main__":
      if Common.HANDLE:
         print("HANDLE在Common里面最初的值为 True")
      else:
         print("HANDLE在Common里面最初的值为 False")
      print("*"*20)
      Test1.change1()
      Test2.change2()
      if Common.HANDLE:
           print("HANDLE为 True")
      else:
           print("HANDLE为 False")
  • main模块的打印结果:


HANDLE在Common里面最初的值为 False
********************
在 Test 里面修改HANDLE为:True
********************
False
在Test2里面 HANDLE 变为 False
********************
HANDLE为 False
  • 分析:在 Test1 里面把 HANDLE 修改为 True 后,为什么在 Test2 里面 HANDLE 的值不是 True,还有就是 Common里面也没有变为 True;
  • 原因:在其他模块 使用 from Common import HANDLE,仅仅是 HANDLE 指向了 Common 里面 HANDLE,在其他模块不会在对 HANDLE 赋值的时候,仅仅是 HANDLE的引用指向发生了变化,并没有修改 Common 里面 HANDLE,说简单了:在其他模块导入from Common import HANDLE,仅仅是定义了 一个 HANDLE 变量;如果你在 Common 里面定义一个列表 list(),在其他模块导入列表的时候,在使用上是 使用列表的一些方法 对列表进行增加减少,那么在其他模块 列表是会发生变化的
  • 解决办法:在其他模块 import Common导入就不会有问题了,再使用 HANDLE 就是 Common. HANDLE,指向的是 Common 这个模块
  • 效果:在Test1与Test2 使用import Common导入, Common. HANDLE 调用


HANDLE在Common里面最初的值为 False
********************
在 Test 里面修改HANDLE为:True
********************
True
在Test2里面 HANDLE 变为 True
********************
HANDLE为 True


四、再议 封装、继承、多态



  • 4.1、为啥要封装?


image.png

image.png

  • 好处


  • 1、在使用面向过程编程时,当需要对数据处理时,需要考虑用哪个模板中哪个函数来进行操作,但是当用面向对象编程时,因为已经将数据存储到了这个独立的空间中,这个独立的空间(即对象)中通过一个特殊的变量(__class__)能够获取到类(模板),而且这个类中的方法是有一定数量的,与此类无关的将不会出现在本类中,因此需要对数据处理时,可以很快速的定位到需要的方法是谁 这样更方便
  • 2、全局变量是只能有1份的,多很多个函数需要多个备份时,往往需要利用其它的变量来进行储存;而通过封装 会将用来存储数据的这个变量 变为了对象中的一个“全局”变量,只要对象不一样那么这个变量就可以再有1份,所以这样更方便
  • 3、代码划分更清晰


  • 4.2、为啥要继承


image.png

  • 说明:


1、能够提升代码的重用率,即开发一个类,可以在多个子功能中直接使用

2、继承能够有效的进行代码的管理,当某个类有问题只要修改这个类就行,而其继承这个类的子类往往不需要就修改


  • 4.3、怎样理解多态


class MiniOS(object):
      """MiniOS 操作系统类 """
      def __init__(self, name):
           self.name = name
           self.apps = []  # 安装的应用程序名称列表
      def __str__(self):
           return "%s 安装的软件列表为 %s" % (self.name, str(self.apps))
      def install_app(self, app):
             # 判断是否已经安装了软件
             if app.name in self.apps:
                  print("已经安装了 %s,无需再次安装" % app.name)
             else:
                  app.install()
                  self.apps.append(app.name)
class App(object):
      def __init__(self, name, version, desc):
            self.name = name
            self.version = version
            self.desc = desc
      def __str__(self):
            return "%s 的当前版本是 %s - %s" % (self.name, self.version, self.desc)
      def install(self):
            print("将 %s [%s] 的执行程序复制到程序目录..." % (self.name, self.version))
class PyCharm(App):
      pass
class Chrome(App):
      def install(self):
           print("正在解压缩安装程序...")
           super().install()
linux = MiniOS("Linux")
print(linux)
pycharm = PyCharm("PyCharm", "1.0", "python 开发的 IDE 环境")
chrome = Chrome("Chrome", "2.0", "谷歌浏览器")
linux.install_app(pycharm)
linux.install_app(chrome)
linux.install_app(chrome)
print(linux)
  • 运行结果


Linux 安装的软件列表为 []
将 PyCharm [1.0] 的执行程序复制到程序目录...
正在解压缩安装程序...
将 Chrome [2.0] 的执行程序复制到程序目录...
已经安装了 Chrome,无需再次安装
Linux 安装的软件列表为 ['PyCharm', 'Chrome']


  • 提示


image.png


在理解多态的时候,相比前两者有点困难,我们可以简单的理解为,我们继承父类之后就拥有了父类的方法,如果父类的方法不能满足的时候,我们可以重写父类的方法,那么父类的方法就不会走了;如果你还想用父类的方法,那么久需要在重写父类的方法下面调用父类的方法,具体是先调用父类的方法,还是后调用父类的方法,那要看我们的处理了

多态的基础理解

目录
相关文章
|
3月前
|
人工智能 Ubuntu IDE
【Python】基础:环境配置与基础语法
本文介绍了Python编程语言及其环境配置方法。Python由Guido van Rossum于1991年创建,以其简洁、易学和强大的功能著称。文章详细讲解了Python的主要特点、Windows和Ubuntu下的安装配置步骤、基础语法、控制流、函数、文件操作、模块使用及面向对象编程等内容,帮助读者快速入门Python编程。
89 4
|
2月前
|
IDE 数据挖掘 开发工具
Python作为一种广受欢迎的高级编程语言,以其简洁的语法和强大的功能吸引了众多初学者和专业开发者
Python作为一种广受欢迎的高级编程语言,以其简洁的语法和强大的功能吸引了众多初学者和专业开发者
40 7
|
23天前
|
算法 Python
Python多继承时子类如何调用指定父类
通过本文的介绍,希望您能够深入理解Python多继承时子类如何调用指定父类的方法,并在实际项目中灵活运用这些技巧,编写出高效且易维护的代码。
27 11
|
22天前
|
算法 Python
Python多继承时子类如何调用指定父类
通过本文的介绍,希望您能够深入理解Python多继承时子类如何调用指定父类的方法,并在实际项目中灵活运用这些技巧,编写出高效且易维护的代码。
33 1
|
2月前
|
存储 索引 Python
Python 的基本语法
这些是 Python 的基本语法要素,掌握它们是学习和使用 Python 的基础。通过不断地实践和应用,你将能够更深入地理解和熟练运用这些语法知识,从而编写出高效、简洁的 Python 代码
79 5
|
2月前
|
存储 Python
Python编程入门:理解基础语法与编写简单程序
本文旨在为初学者提供一个关于如何开始使用Python编程语言的指南。我们将从安装Python环境开始,逐步介绍变量、数据类型、控制结构、函数和模块等基本概念。通过实例演示和练习,读者将学会如何编写简单的Python程序,并了解如何解决常见的编程问题。文章最后将提供一些资源,以供进一步学习和实践。
45 1
|
2月前
|
机器学习/深度学习 数据挖掘 开发者
Python编程入门:理解基础语法与编写第一个程序
【10月更文挑战第37天】本文旨在为初学者提供Python编程的初步了解,通过简明的语言和直观的例子,引导读者掌握Python的基础语法,并完成一个简单的程序。我们将从变量、数据类型到控制结构,逐步展开讲解,确保即使是编程新手也能轻松跟上。文章末尾附有完整代码示例,供读者参考和实践。
|
2月前
|
存储 Python Perl
python正则语法
本文介绍了正则表达式的基础知识及其在 Python 中的应用。首先解释了为什么要使用正则表达式,通过一个判断手机号的示例展示了正则表达式的简洁性。接着详细介绍了 `re` 模块的常用方法,如 `match()`、`search()`、`findall()`、`finditer()` 等,并讲解了正则表达式的基本语法,包括匹配单个字符、数字、锚字符和限定符等。最后,文章还探讨了正则表达式的高级特性,如分组、编译和贪婪与非贪婪模式。
26 2
|
3月前
|
存储 程序员 开发者
Python编程入门:从零开始掌握基础语法
【10月更文挑战第21天】本文将带你走进Python的世界,通过浅显易懂的语言和实例,让你快速了解并掌握Python的基础语法。无论你是编程新手还是想学习一门新的编程语言,这篇文章都将是你的不二之选。我们将一起探索变量、数据类型、运算符、控制结构、函数等基本概念,并通过实际代码示例加深理解。准备好了吗?让我们开始吧!