python基础-函数、面对对象、文件、异常

一、函数

1.1函数

  python允许我们将常用的代码以固定的格式封装(包装)成一个独立的模块,只要知道这个模块的名字就可以重复使用它,这个模块就叫做函数(Function)。

1.2函数的定义和使用

   

  此格式中,各部分参数的含义如下:

    函数名:其实就是一个符合 Python 语法的标识符,但不建议读者使用 a、b、c 这类简单的标识符作为函数名,函数名最好能够体现出该函数的功能(如上面的 my_len,即表示我们自定义的 len() 函数)。

    形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号( , )分隔。

    [return [返回值] ]:整体作为函数的可选参参数,用于设置该函数的返回值。也可以没有返回值,不写返回值,会有一个默认的返回值None,是否需要根据实际情况而定。return后面所有内容都不执行。

   

  其中,函数名即指的是要调用的函数的名称;形参值指的是当初创建函数时要求传入的各个形参的值。如果该函数有返回值,我们可以通过一个变量来接收该值,当然也可以不接受。

  需要注意的是,创建函数有多少个形参,那么调用时就需要传入多少个值,且顺序必须和创建函数时一致。即便该函数没有参数,函数名后的小括号也不能省略。

二、面对对象

2.1概述

  对于面向过程的思想:需要实现一个功能的时候,看重的是开发的步骡和过程,每一个步蒸都需要自己亲力亲为,需要白己编写代码自己来做。

  对于面向对象的思想:当需要实现一个功能的时候,看重的并不是过程和步骤,而是关心谁帮我做这件事。

  面向对象的三大特征有:封结性,继承性.多志性。

 2.2类、创建对象、属性和方法

  

  1.在类内部获取属性和实例方法,通过self获取;

  2.在类外部获取属性和实例方法,通过对象名获取。

  3.如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立的地址;

  4.但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。

  

   init():实例化的时候需要一些自定义的属性,可以使用init()方法

  

 2.3常用方法

  __str__():将__str__()返回的内容以字符串形式输出 

  __str__()方法触发方式:

    1、使用print()函数触发:触发时,会自动寻找实例对象的方法,若没有则直接按照默认内容输出,有则输出__str__方法的返回值。
    2、使用str()函数触发:如上述代码所示,使用str()触发时,worlds类型是str,是一个字符串,打印输出的是一个字符串words。

   print(zhang) 

2.4 对象的继承

  在程序中,继承描述的是多个类之间的所属关系。

  如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。

2.4.1 单继承:子类只继承一个父类

  

  子类在继承的时候,在定义类时,小括号()中为父类的名字。

  父类的属性、方法,会被继承给子类。

 2.4.2 多继承:新建的类可以支持一个或多个父类

   

   

  多继承可以继承多个父类,也继承了所有父类的属性和方法

  当继承了两个或两个以上的类的时候,如果继承的方法或属性有重名,选择继承的第一个。不重名的不受影响。

  子类的魔法属性__mro__决定了属性和方法的查找顺序。

2.4.3子类重写父类属性/方法

  如果子类和父类的方法名和属性名相同,则默认使用子类的。并称为子类重写父类的同名方法和属性。

  

   

2.4.5子类调用父类的同名属性和方法

  当存在继承关系的时候,有时候需要在子类中调用父类的方法,此时最简单的方法是把对象调用转换成类调用,需要注意的是这时self参数需要显式传递。

 

   

  无论何时何地,self都表示是子类的对象。在调用父类方法时,通过传递self参数,来控制方法和属性的访问修改。

  但是这种方式在多层继承中就会有问题(下文super()中会提到),基类Base的构造函数被调用了多次次。这样做还有一些缺点,比如说如果修改了父类名称,那么在子类中会涉及多处修改,在多继承时就需要重复写多次,显得累赘。

2 .4.6 多层继承

  允许多层继承

  

2.4.7 私有权限

  私有权限:在属性名和方法名 前面 加上两个下划线 __

    Python中没有像C++中 public 和 private, protected 这些关键字来区别公有属性和私有属性。Python是以属性命名方式来区分,如果在属性和方法名前面加了2个下划线'__',则表明该属性和方法是私有权限,否则为公有权限。

  类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;

  类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;

  私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。

2.4.8通过super()来调用父类中的方法

  

  默认情况下,python多继承super()方法只会调用第一个父类的方法(后面多继承需要类名.方法名(self))。

  在super机制里可以保证公共父类仅被执行一次。

  使用3.4.5中的方法,就会出现问题,先看看下面的例子:

class Base(object):
    def __init__(self):
        print("enter Base")
        print("leave Base")
 
 
class A(Base):
    def __init__(self):
        print("enter A")
        Base.__init__(self) #调用父类的构造函数进行初始化
        print("leave A")
 
 
class B(Base):
    def __init__(self):
        print("enter B")
        Base.__init__(self) #调用父类的构造函数进行初始化
        print("leave B")
 
class C(A,B):
    def __init__(self):
        print("enter C")
        A.__init__(self) #调用父类A的构造函数进行初始化
        B.__init__(self) #调用父类B的构造函数进行初始化
        print("leave C")
 
 
c=C()

  运行结果:

enter C
enter A
enter Base
leave Base
leave A
enter B
enter Base
leave Base
leave B
leave C

  从上面的运行结果可以看出,基类Base的构造函数被调用了两次,这是有问题的,正常的应该是:A的构造函数调用一次,B的构造函数调用一次,基类Base的构造函数调用一次。

  接下来使用super()进行调用:

class Base(object):
    def __init__(self):
        print("enter Base")
        print("leave Base")
 
 
class A(Base):
    def __init__(self):
        print("enter A")
        super(A,self).__init__()
        print("leave A")
 
 
class B(Base):
    def __init__(self):
        print("enter B")
        super(B,self).__init__()
        print("leave B")
 
class C(A,B):
    def __init__(self):
        print("enter C")
        super(C,self).__init__()
        print("leave C")
 
 
c=C()

  运行结果:

enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C

  可见,父类多次被调用时只执行一次, 优化了执行逻辑。

  具体原因可以看看张同学软件开发写的:彻底搞懂python super函数的作用

三、文件

3.1文件

  使用文件的目的:保存数据存放在磁盘,把一些存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力

3.2文件的打开与关闭

 

3.3文件的读写

# read() 读文件
# 把硬盘里的文件加载到内存中
f = open('test.txt', 'r')
# print(f.read()) 读取文件内所有内容
print(f.read(5))  # 读取5个
print(f.read())  # 读取文件剩余内容
f.close()
# 当文件足够大的时候,内存不够加载整个文件
# 需要一部分一部分加载
f = open('test.txt', 'r')
print(f.readline()) # 读取一行数据
print(f.readlines())  # 读取所有行
f.close()
# 读取汉字时会乱码,需要设置编码格式
f = open('test.txt', 'r', encoding="utf-8")
print(f.readlines())  # 读取所有行
f.close()

# 写数据
# w 如果文件存在,则将其覆盖
f = open('test.txt', 'w')
f.write('hello word, I am zhang')
f.close()

3.4文件、文件夹的相关操作

 

# OS中的rename(需要修改的文件名,新的文件名)可以完成对文件的重命名操作
import os
os.rename("test-复件.txt", "test1.txt")

# OS模块中的remove(待删除的文件名)可以完成对文件的删除操作
os.remove("test1.txt")

# OS模块中的mkdir(文件夹名)可以创建新的文件夹
os.mkdir("a")

# 获取当前目录
os.getcwd()

# 改变默认目录
os.chdir("../")

# 获取目录列表(目录中的所有文件)
print(os.listdir("./"))

# 删除文件夹
os.rmdir("./a")

3.5 应用

# 文件的备份
# 复制文件 test.txt 文件 到test-复件.txt
# 1.获取源文件的名字(包括路径)
filename = input("请输入要备份文件的名称:")
# 2.打开原文件
oldFile = open(filename, "rb")
# 3.获取备份文件的名字 备份文件名字 = 源文件名字 + ”-复件“ + 后缀名
fileFlagNum = filename.rfind(".")  
# 从右往左找找到的必是后缀名(从左往右可能会遇到text.text.txt这种情况) fileFlag = filename[fileFlagNum:] newFileName = filename[:fileFlagNum]+"-复件"+fileFlag# 4.写入备份文件 newfile = open(newFileName,"wb") for linecountent in oldFile.readlines(): newfile.write(linecountent) # 5.关闭文件释放资源 oldFile.close() newfile.close()
#批量在文件名前加前缀
import os

folderName = './aa/'
# 1.获取指定路径的所有文件名宁
dirlist = os.listdir(folderName)
# 2.遍历输出所在文件名字
for name in dirlist:
        newName = '[猫熊出品]-'+ name
os. rename ( folderName+name, folderName+newName )

四、异常处理

4.1 异常

  当Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示, 这就是所谓的"异常”

4.2 捕获异常

  

  可能产生的异常的代码,放在try中。如果产生异常,处理的方法放在except中。

  此处as的作用可以看后文,4.4注。

4.3异常的传递

  

 

 

   通过嵌套,实现异常向外传递。如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。

  

  如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推......如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样。
  如图,test1函数内部产生了异常,异常在test1中没有处理,于是此异常被传递到test3函数完成异常处理,而当异常处理完后,并没有返回到函数test1中进行执行,而是在函数test3中继续执行。

4.4 抛出自定义的异常

  可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类。

class ShortInputException(Exception):
    '''自定义的异常类'''

    def __init__(self, length, atleast):
        super().__init__()
        self.length = length
        self.atleast = atleast

    def __str__(self):  # 使用as查看异常信息的时候,print不会打印任何内容,需要添加一个__str__()使其能够打印出想要的信息
        return 'ShortInputException: 输入的长度是 %d,长度至少应是 %d' % (self.length, self.atleast)
def main():
    try:
        s = input('请输入 --> ')
        if len(s) < 3:
            # raise引发一个你定义的异常
            raise ShortInputException(len(s), 3)
    except ShortInputException as result:  # x这个变量被绑定到了错误的实例
        print(result)
    else:
        print('没有异常发生.')
main()

     注:as声明了一个将保存exception对象的变量。如果说except Exception as e,那么e将是Exception类型的对象。

五、模块和包

5.1 模块

  有过C语言编程经验的朋友都知道在C语言中如果要引用sgrt函敬 ,必须用语句#include <math.h> 引math.h这个头文件,否则是无法正常进行调用的。

  那么在Python中,如果要引用一些其他的函数,该怎么处理呢?

  在Python中有一个概念叫做模块(module) ,模块是在函数和类的基础上,将一系列相关代码组织到一起的集合体。在 Python 中,一个模块就是一个扩展名为 .py 的源程序文件。这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt用数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块

  

5.2 模块制作

  

 

 

   

5.3模块中的__all__

  如果想要以from 自定义包名 import *,需要在包中的__init__.py文件中使用__all__

  

 

 

   建议使用精准导入,多个可以使用逗号隔开。

  

 

 

   重名可以使用as起个别名

5.4包

  

 

 

   

 

 

 

 

  

posted @ 2022-07-20 01:24  石元  阅读(115)  评论(0编辑  收藏  举报