• 上传python笔记,看看博客园的编辑器的效果


    一、Python 中的文件操作

    1.1 文件操作需要了解的前置知识

    1.1.1 为什么需要用到文件操作
    • 如果单纯的将程序需要用到的内容直接的保存在内存中,那么程序每一次执行之后,所保存的数据就会消失,这个时候就需要使用某种方式长期的存储数据,例如保存在文件中,或者保存在数据库中。
    1.1.2 对路径的划分
    • 相对路径:相对于当前文件所在目录的一个路径。通常使用 . 表示当前目录,.. 表示上级目录,通过 ../../ abc.txt 的指令我们可以找到上上级目录下的 abc.txt 文件
    • 绝对路径:从文件的根目录开始计算的路径。在 windows 下,绝对路径通常是以盘符开头的,在 linux/unix 下绝对路径通常是以 / 开头的,例如 C:UsersminDesktopabc.txt就是一个绝对路径。
    • 如果说一个文件它的位置和当前的项目有关,就可以写作相对路径,如果这个文件和系统有关,就可以写成绝对路径,例如网页设计中的资源我们通常会写作相对路径,用于防止目录的泄露。
    1.1.3 二进制文件和文本文件
    • 二进制文件: 指的是拥有特定格式,需要使用对应的算法进行解析的文件,例如可执行文件(.exe)、音频文件(.mp3 .aac)、视频文件(.mp4)、图片文件(.jpg)。
    • 文本文件:其中保存的直接就是字符串,只需要通过基本的文本查看工具就可以打开,不需要专门解析。

    1. 2 文件的操作函数

    1.2.1 文件的基本操作函数

    看看https://zhuanlan.zhihu.com/p/112630994

    • open: 用于打开文件,将文件和文件对象建立关联。其中第一个参数是文件的路径,第二个参数是文件的打开方式,还有一个参数 encoding 用于说明文件的编码类型。

      # 通过 open 函数可以将文件对象和一个文件建立关联
      # 文件的打开方式通常有 r(读) w(写) a(追加) b(在操作二进制文件的时候使用)
      # 函数的返回值是一个文件对象,通过文件对象可以执行相应的文件操作
      file = open(r'data.txt', 'w+')
      
      # 通过 open 函数可以将文件对象和一个文件建立关联
      # 文件的打开方式通常有 r(读) w(写) a(追加) b(在操作二进制文件的时候使用)
      # 函数的返回值是一个文件对象,通过文件对象可以执行相应的文件操作
      try:
          # 使用这个写法会自动的关闭文件,不需要编写 file.close()
          with open(r'data.txt', 'w+') as file:
              file.write('hello world')
      except Exception as e:
          print(e)
      
    • file.close(): 用于关闭一个文件,否则可能产生问题

      # 通常在文件操作完毕之后,需要关闭文件,没有正确的关闭文件可能会导致两个问
      # 题,(1) 文件被占用,在当前项目中无法再次打开文件。(2) 文件的修改无法被应用
      file.close()
      
    • file.write() file.writelines(): 向文件内写入数据

      # 通过 write 一次只能写入一个字符串
      file.write('hello world')
      # 通过 writelines 一次可以写入多个字符串
      file.writelines(['hello', ' world'])
      
    • file.read() file.readlline() file.readlines(): 从文件内读取数据

      # 读取所有内容,可以传入一个参数,表示想要读取的字符数
      print(file.read())
      # 读取一行内容,可以传入一个参数,表示想要读取的字符数
      print(file.readline())
      # 读取文本内的所有内容,将每一行作为一个元素保存到列表中
      print(file.readlines())
      
    1.2.2 文件指针操作函数
    • 文件指针是什么? 文件指针用于标识当前文件的读写位置,通过移动文件指针可以改变读写的起始位置

    • seek: 设置文件的读写位置。

      # 通过 seek 将文件指针移动到倒数第 4 个位置
      # 0: 文件开头开始算起,1:当前位置,2: 文件末尾。
      file.seek(-4, 2)
      print(file.read())
      
    • tell: 获取文件指针当前所在的位置。

      # tell 函数用于获取当前文件指针的位置,可以计算文件大小
      file.seek(0, 2)
      print(file.tell())
      
    1.2.3 通过 os 模块操作文件
    • 需要使用 import os 导入 os 模块,使用其中提供的文件操作函数来操作文件
    • python 的内置文件操作使用的是面向对象的编程方式file.read(),而 os 模块使用面向过程的方式 read(file)
    file = os.open('data.txt', os.O_RDONLY)
    print(os.read(file, 2))
    os.lseek(file, 5, os.SEEK_SET)
    print(os.read(file, 2))
    os.close(file)
    

    二、面向对象编程

    2.1 面向对象和面向过程

    2.1.1 面向过程
    • 思想:程序设计的着眼点在于处理问题的一系列过程(函数)。
    • 特点:数据和处理数据的函数 分离的。
    2.1.2 面向对象
    • 思想:程序设计的着眼点在于解决这个问题所需要的对象有哪些,需要完成什么功能。

    • 特点:封装特性,将数据和处理数据的函数封装到了一起。

    • 三大特性:封装 继承 多态

    2.2 类的编写

    2.2.1 简单的类
    • 通过 class 定义出一个类,一个类其实就是一个自定义的类型,其中描述了某个类别的对象可以实现的功能(方法)和一些描述信息(属性),通过 对象 = 类名() 的方式可以创建出一个对象。
    # 简单类的定义方式,使用关键字 class
    class ClassName(object):
        # 类成员函数,在 python 中被称为方法
        def class_func1(self):
            print('def class_func(self);')
        # 类成员函数,第一个参数必须是 self,后续可以含有其它的参数
        def class_func2(self, value = 100):
            print('def class_func(self, %d);' % value)
    # 通过对象名 = 类名(参数) 的方式可以创建一个对象
    object1 = ClassName()
    object1.class_func1()
    object1.class_func2()
    
    2.2.2 构造函数和析构函数
    • 构造函数:python 中的每一个类中都拥有一个构造函数叫做 __init__,这个函数会被用于执行初始化操作,在一个对象被创建时,自动的调用一次。

    • 析构函数: python 中的每一个类中都拥有一个析构函数叫做 __del__,这个函数会被用于执行清理操作,在对象被删除的时候,自动的调用一次

      # 一个包含构造函数和析构函数的类
      class ClassName2(object):
      
          # 当前类的构造函数,函数可以拥有参数,在创建对象是传入
          def __init__(self, name, age):
              # 在构造函数内执行基本的初始化操作
              print("def __init__(self, %s, %d)" % (name, age))
      
          # 析构函数用于释放资源,但是由于 python 存在垃圾回收机制
          # 所以析构函数使用的比较少,我们可以在其中关闭文件等资源
          def __del__(self):
              # 输出表示析构函数被调用了
              print("def __del__(self)")
      
      # 创建对象时需要传入参数,和构造函数的参数对应,因为创建对象时,会自动调用__init__()函数,当然也会执行里面的语句,在这里是一个print()函数打印相应的内容
      object2 = ClassName2('xiaoming', 18)
      >>>def __init__(self, xiaoming, 18)
      def __del__(self)
      object3 = ClassName2('xiaohong', 80)
      >>>def __init__(self, xiaohong, 80)
      def __del__(self)                                  
      

    关于析构函数何时被调用:

    析构方法__del__是对象在被垃圾回收的时候起作用的一个方法,它的执行一般也就意味着对象不能够继续引用, 回收内存.
    内存回收的方式有两种:

    • 1、当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数会被调用一次,这样可以用来释放内存空间:
    #!/usr/bin/env python
    #-*- coding: utf-8 -*-
    class Foo:
        #初始化方法
        #创建完对象后会自动被调用
        def __init__(self):
            print('构造方法被调用')
        #析构方法
        #当对象被删除时,会自动被调用,然后释放内存
        def __del__(self):
            print('脚本运行结束, 释放内存')
    #创建对象
    f = Foo()
    print('这应该是脚本最后一句.')
    # 这个地方整个文件的作用域就结束了,所以对象f结束其生命周期(因为程序运行停止而结束),系统自动执行析构函数来做清理善后的工作,所以打印"脚本运行结束, 释放内存"成了最后执行的语句.
    运行结果:
        构造方法被调用
    	这应该是脚本最后一句.
    	脚本运行结束, 释放内存
    
    Process finished with exit code 0
    
    • 2、使用del 删除对象时,会调用他本身的析构函数, 相当于手动释放内存
    class Foo:
        #初始化方法
        #创建完对象后会自动被调用
        def __init__(self):
            print('构造方法被调用')
    
        #析构方法
        #当对象被删除时,会自动被调用,然后释放内存
        def __del__(self):
            print('脚本运行结束, 释放内存')
    
    #创建对象
    f = Foo()
    #删除对象
    del f # 删除就立马调用析构函数,(因为del删除对象而结束,对象结束,系统就会调用析构函数)
    print('这应该是脚本最后一句.')
    运行结果:
    	构造方法被调用
    	脚本运行结束, 释放内存
    	这应该是脚本最后一句.
    
    Process finished with exit code 0
    
    2.2.3 实例属性和类属性
    • 实例属性: 具体的某一个对象拥有的属性

    • 通过 self 和 实例名称都可以添加实例属性,添加的属性是归某一个具体的实例所有的。构造函数中的一开始初始化的实例属性会被所有的实例拥有(那是因为所有的实例都会调用构造函数)

      # 一个含有实例属性的类
      class ClassName3(object):
      
          # 构造函数,用于初始化实例属性
          def __init__(self, name, age):
              # 1. 为当前的实例(对象)创建两个个实例属性并进行初始化
              self.age = age
              self.name = name
      
          # 一个方法,调用之后可以添加实例属性
          def add_value(self, v):
              # 2. 通过 self 可以在方法内为调用当前方法的实例添加实例属性,在类外面添加属性:实例名称.属性 = value 进行赋值添加
              self.value = v
      
          # 用于输出当前类内的所有属性
          def print_member(self):
              # __dict__可以输出当前实例内的属性组成的键值对
              print(self.__dict__)
      
      object4 = ClassName3('xiaoming', 80)
      object4.print_member()
      >>>{'age': 80, 'name': 'xiaoming'}
      object5 = ClassName3('xiaohong', 18)
      object5.add_value(30)
      object5.print_member()
      >>>{'age': 18, 'name': 'xiaohong', 'value': 30}
      # 3. 通过实例名称直接的点出属性进行赋值添加
      object4.value2 = 300
      object4.print_member()
      >>>{'age': 80, 'name': 'xiaoming', 'value2': 300}
      
    • 类属性:归整个类所有,被所有的对象共有的属性

    • 通过类名和在类内直接定义可以添加类属性,添加的属性是归所有的实例拥有的

      # 一个含有类属性的类
      class ClassName4(object):
      
          # 1. 在类内的一级缩进内直接定义的属性就是类属性
          class_value = 10
      
          # 构造函数,用于访问类属性
          def __init__(self):
              # 在构造函数中可以使用下面的两种形式访问类属性
              print(self.class_value)
              print(ClassName4.class_value)
      
          # 一个方法,调用之后可以添加类属性
          def add_value(self, v):
              # 2. 通过 类名 可以在方法内为整个类添加一个类属性 3. 在类外也可以通过类名直接的添加属性
              ClassName4.value = v
      
          # 用于输出当前类内的所有属性
          def print_member(self):
              # 实例.__dict__ 保存的是实例内的所有属性
              # 类名.__dict__ 保存的是类内的所有属性
              print('实例', self.__dict__)     # 因为没有实例属性,所以结果是{}
              print('类', ClassName4.__dict__)
      
      object5 = ClassName4()
      object5.print_member()
      >>>
      10
      10
      实例 {}
      类 {'__module__': '__main__', 'class_value': 10, '__init__': <function ClassName4.__init__ at 0x0000027B3F2414C0>, 'add_value': <function ClassName4.add_value at 0x0000027B3F241550>, 'print_member': <function ClassName4.print_member at 0x0000027B3F2415E0>, '__dict__': <attribute '__dict__' of 'ClassName4' objects>, '__weakref__': <attribute '__weakref__' of 'ClassName4' objects>, '__doc__': None}
      # 3. 在类外可以通过类名直接的添加属性
      ClassName4.value2 = 1000
      print(object5.value2)  # 在类外没有这种东西:self.value3 = 2000, self只能在类里面使用
      >>>1000
      object5.print_member()
      >>>
      实例 {}
      类 {'__module__': '__main__', 'class_value': 10, '__init__': <function ClassName4.__init__ at 0x000001EA731D14C0>, 'add_value': <function ClassName4.add_value at 0x000001EA731D1550>, 'print_member': <function ClassName4.print_member at 0x000001EA731D15E0>, '__dict__': <attribute '__dict__' of 'ClassName4' objects>, '__weakref__': <attribute '__weakref__' of 'ClassName4' objects>, '__doc__': None, 'value2': 1000}
      
    • 类属性的访问方式

      # 类属性的访问方式(接上面一段代码的内容)
      object6 = ClassName4()
      >>>
      10
      10
      object6.print_member()
      >>>
      实例 {}
      类 {'__module__': '__main__', 'class_value': 10, '__init__': <function ClassName4.__init__ at 0x00000259999D14C0>, 'add_value': <function ClassName4.add_value at 0x00000259999D1550>, 'print_member': <function ClassName4.print_member at 0x00000259999D15E0>, '__dict__': <attribute '__dict__' of 'ClassName4' objects>, '__weakref__': <attribute '__weakref__' of 'ClassName4' objects>, '__doc__': None}
      # 可以使用 类名 或 实例名 直接点出属性进行访问类
      print(object6.class_value)
      >>>10
      print(ClassName4.class_value)
      >>10
      
      # 不能通过实例.类属性的方式修改属性,这样的操作会创建出一个和类属性同名的实例属性,不管是修改还是访问类属性都推荐使用类名进行操作
      object6.class_value = 1515
      object6.print_member()
      >>>
      实例 {'class_value': 1515}# 果然创建出一个和类属性同名的实例属性
      类 {'__module__': '__main__', 'class_value': 10, '__init__': <function ClassName4.__init__ at 0x00000261AC2314C0>, 'add_value': <function ClassName4.add_value at 0x00000261AC231550>, 'print_member': <function ClassName4.print_member at 0x00000261AC2315E0>, '__dict__': <attribute '__dict__' of 'ClassName4' objects>, '__weakref__': <attribute '__weakref__' of 'ClassName4' objects>, '__doc__': None}
      
      2.3 self 的作用
      • self 用于标识当前函数是被谁调用的,self实际上就是对象的地址 id(object) ,可以进行访问
      # self 的作用
    class ClassName5(object):
      
          # 构造函数,用于初始化实例属性
          def __init__(self, value):
              self.value = value
      
          # 访问实例属性的方法
        def visit_value(self):
              print(hex(id(self)), self.value)
      
      # 对于每一个实例(对象)来说,函数使用的都是相同的,但是实例属性归属于每一个实例自己,函数是通过self区分当前需要用到的数据到底是属于谁的
      
      object7 = ClassName5(100)
        object8 = ClassName5(200)
        object7.visit_value()
        >>>0x1bb49968400 100
        object8.visit_value()
        >>>0x1bb49a52760 200
       
        # 上面的函数调用可以看作 ClassName5(id(object8), 参数)
        print(hex(id(object7)), type(object7))
        >>>0x229bead8400 <class '__main__.ClassName5'>
        print(hex(id(object8)), type(object8))
        >>>0x229bebc1760 <class '__main__.ClassName5'>
      
    

    1、self是什么
    在python的类中self代表实例本身,具体来说,是该实例的内存地址。
    在调用实例的方法时,Python解释器会自己把实例!!变量!!传给类的函数中的self。
    以上述代码I为例,代码I定义了一个类Test,在这个类中,self为参数变量,在类Test实例化得到实例ins时,python解释器自动调用__init__,执行Test.init(ins, 123),该self可接收实例ins的内存地址,从而self代表了实例本身。类似的,如果实例化ins后,执行ins.fun1( ),python解释器会将ins.fun1( )解释成Test.fun1(ins)。可见,self这个变量是无需用户手动传送值的,解释器会自动帮我们给其传递实例。
    需要注意的是,self不是关键字,换言之,可以用其它的合法变量名替换self,但是,规范和标准建议我们一致使用self。

    2、self的使用场景
    在类中,self的使用有下面3个场景:
    1)self为类中的函数的第一个参数,例如在类中,def fun1(self, …)。
    上文说过,“在调用实例的方法时,Python解释器会自己把实例变量传给类的函数中的self”,如果类的函数的第一个参数不是代表实例的self,则调用实例的方法时,该方法没有参数接收解释器自动传入的实例变量,从而程序会产生异常。
    事实上,“和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数”(廖雪峰老师说的)。

    ​ 2)在类中,引用实例的属性,示例:self.变量名(如self.val0)。
    引用实例的属性的目的是为实例绑定属性、写入或读取实例的属性。
    例如,在代码I中,在类的函数__ init __中,“self.val1 = val1”将属性val0绑定到了实例self(类实例化成ins后,self就代表实例ins了)上,并且将变量val1的值赋给了实例的属性val0。在函数fun1中,print(self.val0),读取了实例self的值val0,并打印出来,当然,在函数中修改属性val0的值也是可以的。

    ​ 3)在类中,调用实例的方法,例如,self.fun1();获取实例的方法的地址,例如self.fun1。
    类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。既然,self代表实例,则可以“self.函数名”的方式表示实例的方法地址,以“self.函数名()”的方式,调用实例的方法。在类的定义中,以及实例化后对实例方法的调用,都可以这样做。

    3、python的几种变量——按作用域分
    a、全局变量:在模块内、在所有函数外面、在class外面,这就是全局变量。
    b、局部变量:在函数内、在class的方法内(未加self修饰的) ,这就是局部变量
    c、静态变量(也可以说,类属性):在class内的,但不在class的方法内的,这就是静态变量
    d、实例变量(也可以说,实例属性):在class的方法内的,用self修饰的变量,这就是实例变量

    4、self和变量的关系
    综合上述的1、2和3点,可以得到在类中,self和变量的关系了,一言以蔽之,被self修饰的变量是实例变量,不被self修饰的变量不是实例变量。
    实例变量有什么作用,或者说,什么时候应该使用self修饰变量比较好?我的总结如下:
    当我们想将某个变量绑定给实例时,就在类中,使用self修饰该变量。一般来说,类实例化为不同实例后,为了不同实例的某一变量互不干扰,就将该变量绑定给实例。

    2.4 访问属性控制
    2.4.1 单下划线:文件保护变量
    # 当一个模块内的变量以单下划线开头,则表示这个变量不希望被其它文件访问,以 from m import * 的方式就访问不到这个变量,其它的变量可以照常访问
    from module import *
    # print(_protected_value)
    print(normal_value)
    
    # 通过 import 和 from m import v 的方式都可以照常访问
    import module
    print(module._protected_value)
    
    from module import _protected_value
    print(_protected_value)
    
    2.4.2 双下划线:私有成员
      # 通过代码来了解python 中的保护属性
      class ClassName6(object):
          # 以双下划线开头的是私有属性,不能被外界直接访问
          __value = 12341515
      
      # 私有属性实际就是被解释器改头换面换了名字,具体的格式如下: _ + 类名 + 双下划线开头的属性名,写成这样任然可以访问
      # 改变类的私有变量的值有2种方法:
      # 	间接:为这个私有变量提供一个操作的方法,如:def get_score(self, score)
      # 	直接:实例名._类名__私有变量名 = 值, 如:f._Student__score = 10
    
      print(ClassName6._ClassName6__value)
      >>>12341515
      # 在 python 中,单下划线开头的属性约定俗称通常是不需要
      # 被外界访问的,在写代码或使用第三方库的时候,不要修改
      # 和而访问其它模块中的属性
    

    2.3魔术方法

    __complex__(self)	定义当被 complex() 调用时的行为(需要返回恰当的值)
    __int__(self)	定义当被 int() 调用时的行为(需要返回恰当的值)
    __float__(self)	定义当被 float() 调用时的行为(需要返回恰当的值)
    __round__(self[, n])	定义当被 round() 调用时的行为(需要返回恰当的值)
    __index__(self)	1. 当对象是被应用在切片表达式中时,实现整形强制转换
    	2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 __index__
      3. 如果 __index__ 被定义,则 __int__ 也需要被定义,且返回相同的值
    	上下文管理(with 语句)
    __enter__(self)	1. 定义当使用 with 语句时的初始化行为
    	2. __enter__ 的返回值被 with 语句的目标或者 as 后的名字绑定
    __exit__(self, exc_type, exc_value, traceback)	1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
    	2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作
     容器类型	
    __len__(self)	定义当被 len() 调用时的行为(返回容器中元素的个数)
    __getitem__(self, key)	定义获取容器中指定元素的行为,相当于 self[key]
    __setitem__(self, key, value)	定义设置容器中指定元素的行为,相当于 self[key] = value
    __delitem__(self, key)	定义删除容器中指定元素的行为,相当于 del self[key]
    __iter__(self)	定义当迭代容器中的元素的行为
    __reversed__(self)	定义当被 reversed() 调用时的行为
    __contains__(self, item)	定义当使用成员测试运算符(in 或 not in)时的行为
    
  • 相关阅读:
    正则表达式分组替换注意
    L2 正则化的直观理解
    git版本控制
    callbacks
    validation_data作用
    pandas 对某一列添加过滤
    py-redis 设置过期时间
    什么情况下要做预算会计
    超过一年的一个营业周期是什么意思?
    无形资产为什么属于非流动资产
  • 原文地址:https://www.cnblogs.com/IronMind/p/13235025.html
Copyright © 2020-2023  润新知