美文网首页
Python - Day8

Python - Day8

作者: 姚屹晨 | 来源:发表于2017-10-02 10:09 被阅读17次

    廖雪峰:Python教程

    一.模块

    ①在Python中,一个.py文件就称之为一个模块(Module)

    ②使用模块可以避免函数名和变量名冲突,同名的函数和变量完全可以分别存在于不同的模块中,但是要注意,避免与内置函数名发生冲突。

    所有内置函数.png

    ③如果不同的人编写的模块名相同怎么办?

    • 为了避免模块名冲突,Python引入了按目录来组织模块的方法,称之为包(package)
    package.png
    1.使用模块

    #让该脚本/模块文件在Unix/Linux/Mac上运行
    #!/usr/bin/env python3
    
    #表示脚本/模块本身使用标准UTF-8编码
    # -*- coding: utf-8 -*-
    
    #任何模块代码的第一个字符串均表示模块的文档注释
    'a test module'
    
    #使用__author__变量把作者写进去
    __author__ = 'Gerg'
    
    #导入sys模块后,就有了变量sys指向该模块
    #通过sys这个变量,就可以访问sys模块的所有功能
    import sys
    
    def test():
    #sys模块有一个argv变量,用list存储了命令行的所有参数
    #argv至少有一个参数,因为第一个参数永远是该.py文件的名称
        args = sys.argv
        if len(args) == 1:
            print('Hello,world!')
        elif len(args) == 2:
            print('Hello,%s' %args[1])
        else:
            print('Too mant arguments!')
    #当我们直接运行该模块文件时,Python解释器把一个特殊变量
    #__name__置为__main__;但如果在其他地方导入该模块时,
    #if判断将失败。运行测试
    if __name__ == '__main__':
        test()
    
    1.png

    python编程中的if name == 'main': 的作用和原理

    .py文件有两种使用的方式:第一种是直接作为脚本运行;另一种是import到其他python脚本中被调用(模块重用)执行。

    if __name__ == ''__main___":只有在第一种情况下(即文件作为脚本直接执行)才会被执行。

    第一种作为脚本直接运行.png 第二种方法import到其他的python脚本中被调用执行.png

    ③运行的原理

    加个print__name__直接运行脚本.png 第二种方法.png
    • 注:每个python模块(脚本,这里就是test.pyimport_test.py)都包含内置的变量__name__,当模块被直接运行时,__name__等于文件名(包含后缀.py);如果import到其他模块中,则__name__等于模块名(不包含后缀.py)。而"__main__"等于当前执行文件的名称(包含了后缀.py)。
    2.作用域

    ①正常的函数和变量名都是公开的(public),可以被直接引用。

    ②类似__xxx__这样的变量是特殊变量,可以被直接引用,但有特殊的用途。

    ③类似_xxx__xxx这样的函数或变量就是非公开的(private),不应该被直接引用。

    ④外部不需要引用的函数全部定义为private,只有外部需要引用的函数才定义为public

    3.安装第三方模块

    ①在Python中,安装第三方模块,是通过包管理工具pip完成的。

    二.面向对象编程(Object Oriented Programming)

    ①把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

    ②什么是面向过程的程序设计?

    • 把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为若干子函数。

    ③什么是面向对象的程序设计?

    • 把计算机程序视为一组对象的集合,每个对象都可以接收其他对象发送过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

    ④在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

    ⑤面向过程和面对对象在程序流程上的不同?

    • 面向过程:
    面向过程.png
    • 面向对象:(给对象发消息,实际上就是调用对象对应的关联函数,称之为方法(Method)
    面向对象内包含数据和操作数据的方法.png
    • 面向对象的设计思想是抽离出Class,根据Class创建Instance

    • 面向对象的抽象程序要比函数更高,因为一个Class既包含数据,又包含了操作数据的方法。

    • 面向对象的三大特点:数据封装、继承和多态

    1.类(Class)和实例(Instance)

    ①如何创建实例?

    类型+()创建实例.png

    ②由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把namescore等属性绑上去。

    class Student(object):
        #__init__方法的第一个参数永远是self,表示创建的实例本身。
        #有了__init__方法,在创建实例的时候,就不能传入空的参数了
        #必选传入与__init__方法匹配的参数,但self不需要传。
        def __init__(self,name,score):
            self.name = name
            self.score = score
    
    __init__.png
    2.数据封装

    ①在Student类中,每个实例都拥有各自的namescore这些数据,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要从外面的函数去访问,可以直接在Student类的内部定义访问数据的函数,这样,就把"数据"封装起来了。这些封装数据的函数和Student类本身是由关联的,因此,我们称之为类的方法。

    数据封装.png

    ②封装的另一个好处是可以给Student类增加新的方法,如何get_grade

    封装数据的另一个好处是可以随时为该类添加新的方法.png
    3.小结

    ①类是创建实例的模板,而实例则是一个一个具体的对象,每个实例拥有的数据互相独立、互不影响。

    ②方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据。

    4.访问限制

    ①虽然将数据和操纵数据的方法都封装进一个类中,但仍可以通过外部代码自由修改一个实例的namescore属性:

    仍可以通过外部代码修改类内部的属性.png

    ②如何做到内部属性不被外部访问?

    • 可以在属性的名称前加上两个下划线__
    变量名如果以__开头就变成一个私有变量.png

    ③但是如果外部代码要获取namescore怎么办?

    可以再给类中添加两个方法来获取name和score.png

    ④如果又想允许外部代码修改score怎么办?

    如何修改类中的私有变量.png

    ⑤其实双下划线开头实例变量不一定不能从外部访问,不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,可以通过_Student__name来访问__name变量(强烈不建议那么干,因为不同版本的Python解释器会把__name改成不同的变量名)

    实例对象_Student__name.png

    ⑥一个大坑:

    大坑.png
    • 注:其实这个__name变量和Class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给person1新增了一个__name变量。
    get_name()返回的是内部self__name.png
    5.继承和多态

    ①在OOP程序设计中,当我们定义一个Class时,可以从某个现有的Class继承,新的Class称之为子类(Subclass),而被继承的Class称为基类、父类或超类(Base Class、Super Class)

    子类继承父类的方法.png
    • 注:对于Dog来说,Animal就是它的父类;对于Animal来说,Dog就是它的子类。

    ②继承有什么好处?

    • 最好的好处是子类获得了父类的全部功能。

    ③当子类和父类存在相同的run()方法时,子类的run()会覆盖了父类的run(),在代码运行的时候,总会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。

    多态也就是子类和父类共有一个同名的方法子类会覆盖父类的.png

    ④当我们定义一个Class的时候,实际上我们就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如strlistdict没有什么两样。

    a = list()  #a是list类型
    b= Animal() #b是Animal类型
    c = Dog()   #c是Dog类型
    
    • 如何判断一个变量是否是某个类型?
    • isinstance()
    isinstance.png

    ⑤对于一个变量,我们只需知道它是Animal类型,无需确切地知道它的子类型,就可以放心调用run()方法,而具体调用的run()方法是在AnimalDogCat还是Wangba对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节。

    多态的威力.png

    ⑥什么是"鸭子类型"?

    • 它并不要求严格的继承体系,一个对象只要"看起来像鸭子,走起路来像鸭子",那它就可以被看做鸭子。

    • 对于静态语言,如果需要传入Animal类型,则传入的对象必须是Animal类型或它的子类,否则,就无法调用run()方法。

    • 对于Python这样的动态语言,则不一定需要传入Animal类型,只需保证传入的对象由一个run()方法就可以了。

    6.获取对象信息

    ①如何判断对象的类型?

    • type()函数 - 返回对象Class类型
    判断对象等类型type.png

    ②如果要判断一个对象是否是函数怎么办?

    • 可以使用types模块中定义的常量(FunctionType,BuiltinFunctionType,LambdaType,GeneratorType)
    如何判断一个对象是否是函数使用types模块中定义的常量.png

    isinstance()

    isinstance(content,type).png

    dir() - 获取一个对象的所有属性和方法。

    dir().png

    ⑤配合getattr()setatter()hasattr(),可以直接操作一个对象的状态。

    可以测试对象的属性.png

    ⑥也可以获得对象的方法(赋值给一个变量)。

    获得对象的方法.png
    7.实例属性和类属性

    ①实例属性

    实例属性.png

    ②类属性

    类属性.png

    ③不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性时,再使用相同的名称,访问的将是类属性。

    三.面向对象高级编程

    1.使用__slots__(卡槽)

    ①有什么用?

    • 限制实例的属性。
    __slots__是为了限制实例的属性.png

    __slots__定义的属性只对当前类实例起作用,对继承的子类是不起作用滴。

    __slots__定义的属性对继承的子类不起作用.png
    2.使用@property

    ①在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没有办法检查参数,导致一些神奇的操作:

    s = Student()
    s.score = 9999
    

    ②为了限制score的范围,可以通过set_score()方法来设置成绩,再通过get_score()方法来获取成绩。

    888ValueError.png 88.png

    ③有没有既能检查参数,又能用类似属性这样简单的方式来访问类的变量呢?

    • Python内置的@property装饰器就是负责把一个方法变成属性调用的。
    @property.png 长乘以宽@property.png

    相关文章

      网友评论

          本文标题:Python - Day8

          本文链接:https://www.haomeiwen.com/subject/lhmzextx.html