1 面向对象
1.1 类的构造方法
- __init__构造方法
- 调用时间:在对象被实例化时被程序自动调用
- 作用:用于对象创建时初始化
- 书写格式:init前后分别是2个下划线
- 程序不显示定义init方法,则程序默认调用一个无参数的init方法
- 对象创建过程(无参)
- 设置对象属性(有参)
- 创建对象过程(有参)
1.2 类的方法权限
- 修改对象属性的方法
- 方法1:对象变量名.属性 = 新值
问题:
可能修改的属性值不合法
在类的外部可以随意修改类的内部属性
- 方法2:对象变量名.内部修改属性方法
- 私有属性
- 定义:__私有变量名
- 只能在类内部使用,类外部不能访问,否则报错
- 私有方法
- 只能在类内部调用,在类的外部无法调用
- 定义私有方法在方法名前添加2个下划线:__私有方法()
- 类内部调用私有方法要使用self.私有方法的方式调用
#私有方法的定义&&使用 class Comrade: # 私有方法 def __send_message(self): print("消息已经向上级汇报") def answer_secret(self, secret): if secret == "芝麻开门": print("接头成功!") self.__send_message() # 调用私有方法 else: print("接头失败!") comrade = Comrade() comrade.answer_secret("芝麻开门")
1.3 继承
- 在程序中,继承描述的是类中类型与子类型之间的所属关系,例如猫和狗都属于动物
- 单继承如果在子类中没有定义init构造方法,则自动调用父类的init构造方法;如果子类中已定义init构造方法,则不会调用父类的构造方法
- 子类继承一个父类,在定义子类时,小括号()中写父类的类名
- 父类的非私有属性、方法,会被子类继承
- 子类中方法的查找方式:先查找子类中对应的方法,如果找不到,再到父类中查找
- 子类可以继承父类的非私有属性和方法,也可继承父类的父类的非私有属性和方法,以此类推
- 在子类中调用父类的方法:ClassName.methodname(self)
-
重写父类方法
- 子类对父类允许访问的方法的实现过程进行重新编写
- 在子类中定义与父类同名的方法
- 优点:子类可以根据需要,定义合适的方法实现逻辑
-
多继承
- Object类是所有类的基类,在定义类的时候不需要显示的在括号中表明继承自object类
- 多继承:一个子类可以继承多个父类
- 多继承定义方式:在类名后的括号中添加需要继承的多个类名
- 多继承中,如果多个类中有同名的方法,子类调用查找方法的顺序是按照小括号内继承父类从左到右的顺序查找,第一个匹配的方法名的父类方法将会被调用
-
多态
- 一个抽象类有多个子类,不同的类表现出多种形态
1.4 类属性、类方法、静态方法
- 实例属性(对象属性)
- 在构造方法之内里定义的属性
- 属于具体的实例对象,不同实例对象之间的实例属性互不影响
- 类属性
- 在构造方法之外但在类里定义的属性
- 属于类对象(类名),多个实例对象之间共享同一个类属性
- 获取类属性方法:类名.类属性
- 通过实例对象不能够修改类属性,如果修改的属性在实例中不存在,则动态添加实例属性
#类对象 class Person: sum_num = 0 def __init__(self, new_name): self.name = new_name Person.sum_num += 1 p1 = Person("zhangsan") print(p1.sum_num, Person.sum_num) p2 = Person("lisi") print(p1.sum_num, p2.sum_num, Person.sum_num) #结果显示如下: 1 1 2 2 2
- 类方法
- 所属于类对象,使用@classmethod修饰的方法,主要用于操作类属性,不能操作实例属性
- 定义类方法的第一个参数通常以”cls”参数作为类对象被传入
- 调用方式:类名.类方法 或者 实例对象.类方法(不推荐)
# 类方法 @classmethod def add_sum_num(cls): cls.sum_num += 1 print(cls.sum_num)
- 静态方法
-
使用@staticmethod修饰的方法,不需要传递任何默认参数。不能操作实例属性
-
调用方式:类名.静态方法 或者 实例对象.静态方法
-
@staticmethod def static_test(): print("-------静态方法-------") Person.sum_num += 1 print(Person.sum_num)
1.5 单例类
-
__new__(cls)
-
超类object类内置的方法,用户创建对象,返回创建对象的引用
-
必须提供cls参数,代表类对象
-
必须要有返回值,返回创建对象的引用
-
class DataBaseObj(object): def __init__(self, new_name): # 对象初始化 print("----init构造方法----") self.name = new_name print(self.name) def __new__(cls, name): # 创建对象 print("cls_id:", id(cls)) return object.__new__() # 必须有返回值,返回的是创建的对象的引用
-
单例类
-
在整个程序系统中确保某一类只有一个实例对象
-
# 单例类 class SingleInstance: __instance = None def __init__(self): print("-----init-----") def __new__(cls): if cls.__instance is None: cls.__instance = object.__new__(cls) return cls.__instance s1 = SingleInstance() print(id(s1)) s2 = SingleInstance() print(id(s2))#显示结果
-----init-----
2664579822280
-----init-----
2664579822280
1.6 异常处理
- 捕获异常
try: 逻辑代码块 except ExceptionType as err: 异常处理方法
- 捕获多个异常
try: 逻辑代码块 except (ExceptionType1, ExceptionType2, …) as err: 异常处理方法
- 捕获所有可能发生的异常
try: 逻辑代码块 except (ExceptionType1, ExceptionType2, …) as err1: 异常处理方法 except Exception as err2: 异常处理方法
- finally
try: 逻辑代码块 except (ExceptionType1, ExceptionType2, …) as err1: 异常处理方法 except Exception as err2: 异常处理方法 finally: 无论是否有异常产生,都会执行这里的代码块!
- Python标准异常类型
https://www.runoob.com/python/python-exceptions.html
- 函数嵌套异常传递
1.7 包和模块
一个项目可以包含多个包,一个包可以包含多个模块,一个模块就是一个以.py结尾的文件,一个模块内可以定义变量、函数、类等。
- 模块的名字:.py结尾的文件
- 包下可以包含子包
- 不同包下可以有相同的模块名称,使用“包名.模块名”的方式区分
- 引入模块的方式
引入单个模块:import module_name 引入多个模块:import module_name1, module_name2, … 引入模块中的指定函数: from module_name import func1, func2, …
- 包中必须包含一个默认的__init__文件
用于标识一个包,而不是普通的文件夹
会在包或者该包的模块被引用时自动调用
常用于设置包和模块的一些初始化操作, 比如批量导入时限制部分模块可被导入
2 正则表达式
2.1 re模块的使用
- match(正则表达式,待匹配字符串)
用于正则匹配检查,如果待匹配字符串能够匹配正则表达式,则match方法返回匹配对象,否则返回none
采用从左往右逐项比较匹配
- group()方法
用来返回字符串的匹配部分
import re
rs = re.match("chinahadoop", "chinahadoop.com")
print(rs)
if rs is not None:
print(rs.group())
2.2 字符匹配、数量表示、边界表示
2.2.1 单字符匹配
字符 |
描述 |
. |
匹配除“\n”之外的任意单个字符 rs = re.match(".","a")
|
\d |
匹配0-9之间的一个数字,等价于[0-9] |
\D |
匹配一个非数字字符,等价于[^0-9] |
\s |
匹配任意空白字符,如空格、制表符“\t”、换行“\n”等 rs = re.match("\s","\t")
|
\S |
匹配任意非空白字符 rs = re.match("\S","\t")
|
\w |
匹配任意单词字符(包含下划线),如a-z,A-Z,0-9,_ rs = re.match("\w","a")
|
\W |
匹配任意非单词字符,等价于[^a-zA-Z0-9] |
[] |
匹配[ ]中列举的字符 rs = re.match("[Hh]","hello")
|
^ |
取反 |
2.2.2 数量表示
字符 |
描述 |
* |
一个字符可以出现任意次,也可以一次都不出现 rs = re.match("1\d*","1234567")
|
+ |
一个字符至少出现一次 rs = re.match("\d+","abc")
|
? |
一个字符至多出现一次 rs = re.match("\d?","abc")
|
{m} |
一个字符出现m次 #{m}固定次数
|
{m,} |
一个字符至少出现m次 #{m,}
|
{m,n} |
一个字符出现m到n次 rs = re.match("\d{0,1}","abc") #等价于?至多一次
|
#匹配11位的手机号
#11位,第一位1,第二位3,5,7,8 第3位到第11为0到9的数字
'''
rs = re.match("1[3578]\d{9}","13623198765")
print(rs)
#转义字符处理
str3 = r"hello\\world"#原生字符串
print(str3)
rs = re.match(r"\w{5}\\\\\w{5}",str3)
print(rs)
2.2.3 字符串与单词边界
字符 |
描述 |
^ |
用于匹配一个字符串的开头 |
$ |
用于匹配一个字符串的结尾 #邮箱匹配
|
\b |
用于匹配单词的边界 rs = re.match(r".*\bpython\b","hi python hello")
|
\B |
用于匹配非单词边界 rs = re.match(r".*\Bth\B","hi python hello")
|
2.2.4 匹配分组
字符 |
描述 |
| |
表示或,匹配 | 链接的任何一个表达式 |
() |
将括号中字符作为一个分组 import re
|
\NUM |
配合分组()使用,引用分组NUM(NUM表示分组的编号)对应的匹配规则 #\num
|
(?P<name>) |
给分组起别名 rs = re.match(r"<(?P<g1>.+)><(?P<g2>.+)>.+</(?P=g2)></(?P=g1)>",html_str)
|
(?P=name) |
应用指定别名的分组匹配到的字符串 |
2.3 高级用法
- search:从左到右在字符串的任意位置搜索第一次出现匹配给定正则表达式的字符
#search
rs = re.search("car","haha car carbal abcar carbal")
print(rs)
- findall:在字符串中查找所有匹配成功的组,返回匹配成功的结果列表
#findall
rs = re.findall("car","haha car carbal abcar carbal")
print(rs)
mail_str = "zhangsan:helloworld@163.com,li:123456@qq.cn"
list = re.findall(r"(\w{3,20}@(163|qq)\.(com|cn))",mail_str)
print(list)
- finditer:在字符串中查找所有正则表达式匹配成功的字符串,返回iterator迭代器
#finditer
itor = re.finditer(r"\w{3,20}@(163|qq)\.(com|cn)",mail_str)
for it in itor:
print(it.group())
- sub:将匹配到的数据使用新的数据替换
#sub
str = "java python c cpp java"
rs = re.sub(r"java","python",str)
print(rs)
- split:根据指定的分隔符切割字符串,返回切割之后的列表
#split
str_test = "apple=5,banana=3,orange=2"
price_list = str_test.split(",")
for price in price_list:
print(price)
2.4 贪婪与非贪婪模式
- 贪婪模式:正则表达式引擎默认是贪婪模式,尽可能多的匹配字符,匹配数量为上限
#贪婪模式
rs = re.findall(r"hello\d*","hello12345")
print(rs)
rs = re.findall(r"hello\d+","hello12345")
print(rs)
rs = re.findall(r"hello\d?","hello12345")
print(rs)
rs = re.findall(r"hello\d{2,}","hello12345")
print(rs)
rs = re.findall(r"hello\d{1,3}","hello12345")
print(rs)
- 非贪婪模式:尽可能少的匹配字符;在表示数量的“*”,“?”,“+”,“{m,n}”符号后面加上?,使贪婪变成非贪婪。匹配数量为下限
#非贪婪模式
rs = re.findall(r"hello\d*?","hello12345")
print(rs)
rs = re.findall(r"hello\d+?","hello12345")
print(rs)
rs = re.findall(r"hello\d??","hello12345")
print(rs)
rs = re.findall(r"hello\d{2,}?","hello12345")
print(rs)
rs = re.findall(r"hello\d{1,3}?","hello12345")
print(rs)