学习Python进阶!!!

类与对象

类,简单理解就相当于一个图纸,在程序中需要根据类来创建对象,类就是对象的图纸,而对象是类的实例

对象的创建流程
  1. 创建一个变量
  2. 在内存中创建一个新对象
  3. 执行类中代码块中的代码
  4. init__(self)方法执行
  5. 将对象的id赋值给变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L005Elha-1611136578559)(images/图片1.png)]

类的定义

类和对象都是对现实生活的或者程序中的内容的抽象

类的组成:

  • 数据(属性)
  • 行为(方法)

调用方法,对象.方法名()

方法调用和函数调用的区别:

  • 函数调用,则调用时传几个参数,就会有几个实参
  • 方法调用,默认传递一个参数,所以方法中至少有一个形参
class Person:
    name = 'May'

    def sayHello(param):
        print("世界", '你好')


per = Person()

print(per.sayHello())

类的特殊方法init

类的基本结构:

class 类名([父类]):
    
    公共的属性...
    
    # 对象的初始化方法
    def _init_(self,...):
        ...
        
    # 其它方法
    def mothod(self,..):
        ...

实例:

class Person:

    def __init__(self, name):
        # print('特殊方法执行')
        self.name = name

    def sayHello(self):
        print("%s 你好" % self.name)

per = Person("世界")

per.sayHello()


封装

封装指的是隐藏对象中一些不希望被外部所访问到的属性和方法

封装方法一

需要提供一个getter和setter方法使外部可以访问到属性

  • getter:获取对象中的指定属性
  • setter:用来设置对象的指定属性
class Dog:
    
    def _init_(self, name):
        self.hidden_name = name
        
    def sayHello(self):
        print("我是 %s" % self.hidden_name)
        
    def getName(self):
        return self.hidden_name
    
    def setName(self, name):
        self.hidden_name = name
        
dog = Dog("小黑")
dog.sayHello()
封装方法二

可以为对象的属性使用双下划线开头,_XXX双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象访问

注意:其实隐藏属性只不过是Python自动为属性改的一个名字,实际上是将名字修改为,_类名__属性名

class Person:
    
    def __init__(self, name):
        self.__name = name
        
    def getName(self):
        return self.__name
    
    def setName(self, name):
        self.__name = name
        
per = Person("May")
封装方法三

property装饰器:用来将一个get方法转换为对象的属性,添加property装饰器以后我们就可以像调用属性一样使用get方法,使用property装饰的方法,必须和属性名一样

class Person:

    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

    # setter 方法的装饰器:@name.setter
    @name.setter
    def name(self, name):
        self._name = name

per = Person("May")

per.name = 'May五月'
print(per.name)

继承

继承的简介

继承可以使一个类获取其它类中的属性和方法,在定义类时,可以在类名后的括号中指定当前类的父类(超类、基类、super),通过继承之后子类可以直接继承父类中的所有的属性和方法

class Animal:

    def run(self):
        print('跑跑跑.....')

    def bark(self):
        print('叫叫叫.....')

class Dog(Animal):

    def sleep(self):
        print('睡觉时间到了.....')

class Hashiqi(Dog):

    def name(self):
        print('我是哈士奇.....')

animal = Dog()
dog = Hashiqi()
animal.bark()
dog.name()

当我们调用一个对象的方法时:

​ 会优先去当前对象中寻找是否具有该方法,如果有则直接调用

​ 如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法

​ 如果没有,则去父类的父类中寻找,以此类推,直到找到object,如果依然没有找到,则报错

super()
class Animal:

    def __init__(self, name):
        self._name = name

    def run(self):
        print('跑跑跑.....')

    def bark(self):
        print('叫叫叫.....')


class Dog(Animal):

    def __init__(self, name, age):
        super().__init__(name)
        self._age = age

    def sleep(self):
        print('睡觉时间到了.....')

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, age):
        self._age = age


animal = Dog('May', 18)
print(animal.name)
print(animal.age)

在Python中支持多继承,也就是我们可以为一个类同时指定多个父类,可以在类名的()后边添加多个类,来实现多重继承,多重继承,会使子类同时拥有多个父类,并且会获取到所有父类中方法

类名._bases_这个属性可以用来获取当前类的所有父类

在开发中没有特殊的情况下,应该避免使用多继承,因为多重继承会让我们的代码过于复杂

多态

简介

一个对象可以以不同的形态去呈现

面向对象三大特征:

  • 封装
    • 确保对象中的数据安全
  • 继承
    • 保证了对象的可扩展性
  • 多态
    • 保证了程序的灵活性

属性和方法

类属性和方法
类属性:

定义:直接在类中定义的属性是类属性

类属性可以通过类或者类的实例访问到,但是类属性只能通过类对象来修改,无法通过实例对象来修改

类方法:

在类内部使用@classmethod来修饰的方法属于类方法

类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象

​ 类方法和实例方法的区别,实例方法的第一个参数是self,类方法的第一个参数是cls

​ 类方法可以通过类方法调用,也可以通过实例调用,没有区别

实例属性

定义:通过实例对象添加的属性属于实例属性

实例属性只能通过实例对象来访问和修改,类对象无法访问修改

实例方法:

在类中定义,以self为第一个参数的方法都是实例方法

实例方法在调用时,Python会将调用对象作为self传入

实例方法可以通过通过实例和类去调用

​ 当通过实例调用时,会自动将当前调用对象作为self传入

​ 当通过类调用时,不会自动传递self,此时我们必须手动传递self

静态方法

在类中使用@staticmethod来修饰的方法属于静态方法

静态方法不需要指定任何的默认参数,静态方法可以通过类和实例去调用

静态方法,基本上是一个和当前类无关的方法,它只是一个保存在当前类中函数

静态方法一般都是一些工具方法,和当前类无关

class Person:
    """
    类属性可以通过类或者类的实例访问到,
    但是类属性只能通过类对象来修改,
    无法通过实例对象来修改
    """
    count = 0
    # 类方法可以通过类方法调用,也可以通过实例调用
    @classmethod
    def person(cls):
        print("该方法是类方法...")

    # 实例方法
    # 实例方法可以通过通过实例和类去调用
    #   当通过实例调用时,会自动将当前调用对象作为self传入
    #   当通过类调用时,不会自动传递self,此时我们必须手动传递self
    def instance(self):
        print(self, "调用该方法...")


per = Person()
per.count = 5
# 通过实例对象和类对象调用类属性
print(per.count)
print(Person.count)
# 通过实例对象和类对象调用类方法
per.person()
Person.person()
# 通过实例对象和类对象调用实例方法
per.instance()
Person.instance(per)

特殊方法

特殊方法也称为魔术方法。

特殊方法都是使用____开头和结尾的,特殊方法一般不需要手动调用,需要在一些特殊的情况下自动执行

  • r_str_()这个特殊方法会在尝试将对象转换为字符串的时候调用
    • 它的作用可以用来指定对象转换为字符串的结果
  • r_repr_()这个特殊方法会在对当前对象使用repr()函数时调用
    • 它的作用是指定对象在“交互模式”中直接输出的效果
  • r_gt_()会在对象做大于比较的时候调用,该方法的返回值将会作为比较的结果
    • 它需要两个参数,一个self表示当前对象,other表示和当前对象比较的对象
  • ….特殊方法有很多

模块化

模块化:将一个程序分解为一个一个小的模块

模块化的特点:

  1. 方便开发
  2. 方便维护
  3. 模块可以复用

在一个模块中引入外部模块

  • import 模块名(模块名就是python文件的名字)

  • import 模块名 as 模块别名

    • 可以引入同一个模块多次,但是模块的实例只会创建一个
    • import可以在程序的任何位置调用,但是在一般情况下,import语句都会统一写在程序的开头
    • 在每一个模块的内部都会有一个__name__属性,通过这个属性可以获取模块的名字
    • 主模块就是我么直接通过 python 执行的模块
  • from 模块名 import 模块中需要的部分

  • from 模块名 import *

    • 导入模块中的所有内容
    • 但是如果想限制获取的内容,可以在模块中使用____all = [使用*可以访问到的内容]
包中init文件

只要导入包,包中的init文件就会首先执行

作用:

  • 但导入包的时候,把一些初始化的函数、变量、类定义在__init__.py文件中
  • 此文件中函数,变量等的访问,只需要通过包名.函数…
  • 结合__all__= [通过 * 可以访问的模块]

正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是事先定义一些特定的字符,及这些字符的组合,组成一个规则字符串,这个规则字符串就称为正则表达式

正则表达式又称为正则表式式,规则表达式,常规表达式

正则表达式的作用:
  • 给定的字符串是否符合正则表达式的过滤逻辑
  • 可以通过正则表达式,从字符串中获取我们想要的特定部分
正则表达式的特点:
  • 灵活性、逻辑性和功能性非常强
  • 可以迅速的用极简单的方式达到字符串的复杂控制
  • 对于刚接触的人来说,比较难懂
正则表达式模块中方法

match 匹配方法是从头进行匹配,如果匹配不成功就返回None

search 方法进行正则字符串匹配方法,匹配的是整个字符串

group 用来提取匹配到的内容部分

sub 替换

split 分割

# 导入正则表达式模块
import re

str = '五月六月七月'

# match 匹配方法是从头进行匹配,如果匹配不成功就返回None
result = re.match('五月', str)
print(result.span())

# search 方法进行正则字符串匹配方法,匹配的是整个字符串
result1 = re.search('七月', str)
print(result1.span())

#  group 用来提取匹配到的内容部分
print(result.group())
print(result1.group())

匹配字符:

  • . 表示任意的字符

  • ^是开头

  • $表示的是结尾

  • [] 表示的是一个范围

  • *用于将前面的模式匹配零次或者是多次

  • +用于将前面的模式匹配一次或者是多次

  • ?用于将前面的模式匹配一次或者是零次

  • {m} 用于验证前面的模式匹配 m 次

  • {m,}用于验证将前面的模式匹配 m 次或者大于 m 次

  • {m, n}用于验证前面的模式匹配大于等于 m 小于等于 n 次

# 导入正则表达式模块
import re

str = 'adsa46da56'

# [] 表示的是一个范围
# search 方法匹配到一个就不在继续往下找
result = re.search('[a-z][0-9][0-9]', str)
print(result.group())

# findall 方法匹配整个字符串,找到一个继续向下找,一直找到字符串的结尾
result1 = re.findall('[a-z][0-9][0-9]', str)
print(result1)

result2 = re.findall('[a-z][0-9]+', str)
print(result2)

\A:表示从字符串的开始出匹配
\Z:表示从字符串的结束处开始匹配,如果存在换行,只匹配到换行前的结束字符串。
\b:匹配一个单词边界,也就是指单词和空格间的位置。例如'py\b'可以匹配到'python'中的'py'
\B:匹配非单词边界
\d:匹配任意数字,等价于[0-9]
\D:匹配任意非数字字符
\s:匹配任意空白字符
\S:匹配任意非空白字符
\w:匹配任意字母数字及下划线
\W:匹配任意非字母数字及下划线
\\:匹配原意的反斜杠

分组匹配

()表示分组,group(1) 表示第一组的内容,group(2) 表示第二组的内容

import re

msg = '<html>abc</html>'

result = re.match(r'<[0-9a-zA-Z]>(.+)</\1>')
print(result.group(1))

起名

起名的方式为:(?P<起的名字>)

引用:</(?P=起的名字)>

贪婪和非贪婪

贪婪:总是尝试匹配尽可能多的字符

非贪婪:总是匹配尽可能少的字符

如果贪婪模式想转变为非贪婪模式,只需要在正则表达式的后面加上==?==,默认是贪婪的

import re
# 默认是贪婪的,如果想将贪婪模式变为非贪婪模式,只需要在正则表达式后面加上?即可
msg = 'abc123as'

result = re.match(r'abc(\d+?)', msg)

print(result)

进程

异常

处理异常的语句:

try:
    代码块(可以出现错误的语句)
except:
    代码块(出现错误之后的处理方式)
else:
    代码块(没有错误是要执行的语句)
finally:
    代码块(该代码块总会执行)

异常传播:当在函数中出现异常时,如果对异常进行处理,则异常不会再继续传播,如果没有对异常进行处理,则异常会继续向函数调用处传播,如果函数调用处处理了异常,则不会传播,如果没有处理则继续向调用处传播,直到传递到全局作用域(主模块)如果依然没有处理异常,则程序终止,显示异常信息。

当程序运行过程中出现异常后,所有的异常信息都会保存到一个专门的异常对象中,而异常传播就是异常对象抛给了调用处

异常对象
  • 如果except后面不跟任何内容,则此时会捕获到所有的异常;
  • 如果在except后面跟上一个异常的类型,则此时只会捕获该类型的异常;
print('异常执行前:')

try:
    print(May)
    # print(10/0)
except NameError:
    print('出现 NameError 错误')
except ZeroDivisionError:
    print('出现 ZeroDivisionError 错误')
except IndexError:
    print('出现 IndexError 错误')
    # Exception 是所有异常类的父类,所以如果except后跟的是Exception,它也会捕捉到所有的异常
    #  可以在异常类后面跟着一个 as xx 此时 xx 就是异常对象
except Exception as e:
    print('未知异常', e)
finally:
    print('该段程序总会执行')

print('异常出现后')

自定义异常对象

自定义异常的格式:

class 类名(Exception):
    代码块

raise:可以向外部抛出异常,后面可以跟一个异常类,或者是异常类的实例

# 自定义异常
class MyException(Exception):
    pass

# 求两个数的和,要求两个数不能是负数
def add(a, b):
    if a < 0 or b < 0:
        raise MyException('出现负数')
    r = a + b
    return r

print(add(-23, 32))

文件

打开文件

python通过调用open()来打开一个文件,可以将文件分成两种类型

  • 纯文本文件(使用utf-8等编码编写的文件)
  • 二进制文件(图片、mp3、PPT等文件)

open()打开文件时默认是以文本的形式打开的,但是open(),默认的编码是None所以处理文件时,补习指定文件的编码

file_name = 'File.txt'
try:
    with open(file_name, encoding = 'utf-8') as file_obj:
        print(file_obj.read())
except Exception as e:
    print('未知错误', e)

读取文件和关闭文件

**read()**方法用来读取文件中的内容,它会将内容全部保存为一个字符串返回。read()参数默认是-1,一次读取所有的字符,如果给read()写入参数n,则一次读取n个字符

**close()**用来关闭已经打开的文件

# 打开文件
file_name = 'File.txt'

file_obj = open(file_name)

# 当我们获取了文件对象以后,所有的文件的操作都应该通过对象进行
# read()方法用来读取文件中的内容,它会将内容全部保存为一个字符串返回
centent = file_obj.read()

print(centent)
# 关闭文件
file_obj.close()

读取大文件:

file_name = 'File.txt'

try:
    with open(file_name, encoding="utf-8") as file_obj:
        # 定义一个变量,来指定每次读取的大小
        chunk = 100
        
        while True:
            content = file_obj.read(chunk)
            # 检查是否读取到了内容
            if not content:
                break
            print(content)
except FileNotFoundError:
    print(f'{file_name} 这个文件不存在')

with…as 语句

在with语句中可以直接使用file_obj来做文件操作,此时这个文件只能在with中使用,一旦with结束后文件自动关闭

file_name = 'File.txt'
try:
    with open(file_name) as file_obj:
        print(file_obj.read())
except Exception as e:
    print('未知错误', e)

写入文件

参数表示的含义:

  • r 表示只读

  • x 表示用来创建文件,如果文件不存在就创建,存在则报错

  • w 表示可以,使用 w 来写入文件时,如果文件不存在会创建文件,如果文件存在则会截断文件

    截断文件指的是删除原来文件中的所有内容

  • a 表示追加内容,如果文件不存在会创建文件,如果文件存在会向文件中追加内容

  • +为操作符增加功能

    • r+ 即可读又可写,文件不存在会报错

    • w+ 即可写又可读

    • a+ 即可追加又可读

file_name = 'File.txt'

# 使用open()打开文件必须要指定打开文件所需要做的操作(读、写、追加)
# 如果不指定操作类型,则默认是读取文件,而读取文件是不能向文件中写入的
# r 表示只读
# x 表示用来创建文件,如果文件不存在则创建爱你,存在则报错
# w 表示可以,使用 w 来写入文件时,如果文件不存在会创建文件,如果文件存在则会截断文件
#   截断文件指的是删除原来文件中的所有内容
# a 表示追加内容,如果文件不存在会创建文件,如果文件存在会向文件中追加内容
# + 为操作符增加功能
# r+ 即可读又可写,文件不存在会报错
# w+ 即可写又可读
# a+ 即可追加又可读
with open(file_name, 'w', encoding='utf-8') as file_obj:
    file_obj.write("有时候,我们活得累,")
    file_obj.write('并非生活过于刻薄,而是我们太容易被外界的氛围所感染,')
    file_obj.write('被他人的情绪所左右')

二进制文件
  • b 表示读取二进制文件

  • 读取文本文件时,是以字符为单位的

  • 读取二进制文件时,是以字节为单位的

file_name = '二进制文件的路径'

# t 读取文本文件
# b 读取二进制文件

with open(file_name, 'rb') as file_obj:
    # 读取文本文件时,size是以字符为单位的
    # 读取二进制文件时,size是以字节为单位的
    
    # 将读到的二进制文件再写入文件中
    new_name = '写入文件的名称'
    
    with open(new_name, 'ab') as new_obj:
        # 定义每次读取的大小
        chunk = 100 *  1024
        
        while True:
            # 从已有对象中读取数据
            content = file_obj.read(chunk)
            
            if not content:
                break
                
            new_obj.write(content)

seek()和tell()

seek():可以修改当前读取的位置

seek():需要两个参数

  • 第一个 参数,是要切换到的位置
  • 第二个参数,计算位置的方式
    • 0 从头计算,默认值
    • 1 从当前位置计算
    • 2 从最后位置开始计算

猜你喜欢

转载自blog.csdn.net/qq_44880095/article/details/112983234