python4
Python1-环境配置
Python2-基础认识
Python3-数据类型
Python4-面向对象
Python5-闭包和装饰器
Python6-IO模块
Python7-进程线程携程
Python8-网络编程
Python爬虫
函数和对象基础
模块
一个.py文件就是一个模块,可以包含n多个函数,可以包含n多个类
类当中可以包含:
- 类属性
- 实例方法(实例属性)
- 类方法
- 静态方法
还可以包含n多个语句
n多个模块组成Python程序(项目),一个项目中有n多个模块
用处:
- 团队协作开发
- 可复用性
- 可维护性
- 可以避免函数名和变量名冲突
模块的展示
def fun():
pass
def fun2():
pass
class Student:
native_plce = '吉林' # 类属性
def eat(self,name,age): # 实例方法方法
self.name = age # 实例属性
self.age = age
@classmethod # 类方法
def cm(cls):
pass
@staticmethod # 静态方法
def sm():
pass
a = 19
b = 20
print(a+b)
模块导入
# 第一部分是standard library
# 第二部分是third party library
# 最后是local的库
# 先写import 后写from ... import ...
# 同级别后进行字典排血
# 现在已经有实现的代码和插件了:pip install isort和vscode中的isort插件
'''import 模块名 [as别名]'''
import math # 关于数学运算的模块
print(id(math))
print(type(math))
print(math)
print(math.pi)
print(dir(math))
print(math.pow(2, 3), type(math.pow(2, 3)))
print(math.ceil(9.001))
print(math.floor(9.999))
'''from 模块名称 import 函数/变量/类'''
from math import pi
print(pi)
print(pow(2, 3))
print(math.pow(2, 3))
导入自定义的模块
以主程序形式运行
目录结构
目录结构
|--module
|--__init__.py
|--test.py
|--test2.py
test.py
class cs:
def __init__(self,name='张三'):
self.name = name
def fire():
print("发射子弹")
print("**------->")
def grenades():
print("投掷手雷")
print("****************")
def die(self):
print(f"{self.name}阵亡")
test2.py
import test
import random
def determine(name:str):
test.cs.fire()
r = random.randint(0,60)
if r >= 30:
test.cs(name).die()
determine("李四")
test.cs.grenades()
出现的问题
如果某个目录需要升级为模块,供其他调用,在该目录下添加 init.py
某个目录下的py文件,需要调用其他模块,需要将该py文件的父目录加入path
import os
# 获取项目根目录
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 获取Configs目录路径
CONFIG_DIR = os.path.join(BASE_DIR, 'Configs')
# 获取配置文件路径
CONFIG_FILE_PATH = os.path.join(CONFIG_DIR, 'init.ini')
# 获取TestDatas目录路径
DATAS_DIR = os.path.join(BASE_DIR, 'TestDatas')
# 获取excel文件路径
DATAS_FILE_PATH = os.path.join(DATAS_DIR, 'TestDatas.xlsx')
# 获取Logs目录路径
LOGS_DIR = os.path.join(BASE_DIR, 'Logs')
# 获取Reports目录路径
REPORTS_DIR = os.path.join(BASE_DIR, 'Reports')
# 获取TestCases目录路径
CASES_DIR = os.path.join(BASE_DIR, 'TestCases')
init.py文件的解释
导入package的时候__init__.py起引导作用
import package1
执行代码后会先执行package文件下的__init__.py文件,然后引用。
在Python3.2之前是必须创建且写入的,在之后的文件中可以不用建立。
init.py文件中可以写入预执行语句比如导入数据库等,提前进行,可以使程序运行速度提升,还有利于程序的可以读性。
回调
目录结构
|--module
|--__init__.py
|--test.py
|--test2.py
test.py
import test2 as t
def display():
print('main - display')
if __name__ == '__main__':
t.show('hello',display)
test2.py
def show(msg,func):
print('show',msg)
func()
print('show-over')
def display():
print('display')
if __name__ == '__main__':
show('hello',display)
包
# 包和文件夹的区别为是否有__init__.py的文件
# 导入package包
import package.module_A as pma # pma为package.module_A的别名
# print(package.module_A.a)
print(pma.a)
# 导入带有包的模块时注意事项
import package
import calc
# 使用import方式进行导入时,只能跟包名或模块名称
from package import module_A
from package.module_A import a
# 使用from...import 方式进行导入包时,可以导入包,模块,函数,变量
python常用内置模块
- sys 与Python解释器及其环境操作相关的标准库
- time 提供与时间相关的各种函数的标准库
- OS 提供了访问操作系统服务功能的标准库
- calendar 提供与日期相关的各种函数的标准库
- urllib 用于读取来自网上(服务器)的数据标准库
- json 用于使用JSON序列化 和反序列化对象
- re 用于在字符串中执行正则表达式匹配和替换
- math 提供标准算术运算函数的标准库
- decimal 用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算
- logging 提供了灵活的记录事件、错误、警告和调试信息等目志信息的功能
'''
sys 与Python解释器及其环境操作相关的标准库
time 提供与时间相关的各种函数的标准库
OS 提供了访问操作系统服务功能的标准库
calendar 提供与日期相关的各种函数的标准库
urllib 用于读取来自网上(服务器)的数据标准库
json 用于使用JSON序列化 和反序列化对象
re 用于在字符串中执行正则表达式匹配和替换
math 提供标准算术运算函数的标准库
decimal 用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算
logging 提供了灵活的记录事件、错误、警告和调试信息等目志信息的功能
'''
import sys
import time
import urllib.request
import math
print(sys.getsizeof(24))
print(sys.getsizeof(45))
print(sys.getsizeof(True))
print(sys.getsizeof(False))
print(time.time())
print(time.localtime(time.time()))
print(urllib.request.urlopen('http://www.baidu.com').read())
print(math.pi)
第三方模块安装
pip install 模块名
import schedule
import time
def job():
print('haha')
schedule.every(3).seconds.do(job)
while True:
schedule.run_pending()
time.sleep(1)
Python定时删除数据库中大量数据 / 定时任务
import time
import pymysql
from apscheduler.triggers.cron import CronTrigger
from apscheduler.schedulers.blocking import BlockingScheduler
def delete_data():
# 连接本地数据库, user:数据库用户,password:密码, db:数据库名称
conn = pymysql.connect(host='127.0.0.1', user='****', password='*****', port=3306, db='***')
if not conn:
print('连接失败')
cur = conn.cursor()
new_time = time.time() # 获取当前时间
# 将当前两周之前的时间戳转为时间字符串
create_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(new_time - 7 * 24 * 3600))
cur.execute('select id from user where create_time<%s order by id desc', create_time) # 查询两周之前的数据,并降序排序
select_result = cur.fetchall() # 获取查询结果
id = select_result[0] # 获取查询结果中的id
print(id)
cur.execute('delete from user where id<%s limit 1000', id) # 按id进行删除,每次删除1000条数据
conn.commit() # 提交
cur.close()
conn.close()
if __name__ == '__main__':
scheduler = BlockingScheduler()
# 每天定时在16:00到16:30执行该函数
cron = CronTrigger(
second='0-59', # 秒
start_date=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), # 开始时间
minute='0-30', # 分
hour=16, # 小时
timezone='Asia/Shanghai') # 中国时间
scheduler.add_job(id='timing', trigger=cron, func=delete_data) # 添加计时任务
scheduler.start() # 计时开始
函数
函数的用途:
代码复用,隐藏实现细节,提高可维护性,提高可读性便于调用
# a,b为形式参数,形参的位置是在函数的定义处
# :后可以指定参数类型,->可以设定返回参数类型
def carc(a:int, b) -> str:
c = a + b
return c
result = carc(10, 20) # 10,20为实际参数的值,实参的位置在函数调用处
print(result) # a:10 b:20位置传参
carc(b=10, a=20)
print(result) # 关键字传参,等号左侧的名称为关键字
def fun(arg1, arg2):
print('arg1', arg1)
print('arg2', arg2)
arg1 = 100
arg2.append(10)
print('arg1', arg1)
print('arg2', arg2)
return
n1 = 11
n2 = [22, 33, 44]
print('n1', n1)
print('n2', n2)
fun(n1, n2) # 位置传参 arg1,arg2,是函数定义处的形参,n1,n2是函数调用处的实参, 实参和形参名称可以不一样
print('n1', n1)
print('n2', n2)
'''在这个函数的调用过程中,进行参数的传递
如果是不可变对象,在函数体内的修改不会影响到实参的值
arg1的修改为100,不会影响n1的值
如果是可变对象,在函数体内的修改会影响到实参的值
arg2的修改,append(10),会影响到n2的值
'''
函数的返回值
print(bool(0)) # False
print(bool(8)) # True
def fun(num):
odd = []
even = []
for i in num:
if i % 2:
odd.append(i)
else:
even.append(i)
return odd, even
lst = [10, 29, 34, 23, 44, 53, 55]
print(fun(lst))
函数的返回值
- 如果函数没有返回值,函数调用执行完毕后,不需要给调用处提供数据,return可以省略不写
- 函数的返回值,如果是一个,直接返回类型
- 函数的返回值,如果是多个,返回结果为元组
def fun1():
print('hello')
fun1()
def fun2():
return 'hello'
res = fun2()
print(res)
def fun3():
return 'hello', 'world'
print(fun3())
'''函数在定义时,是否需要返回值,视情况而定'''
函数的参数定义
函数定义默认值参数
def funn(a, b=10):
print(a, b)
funn(100)
funn(20, 30)
个数可变的位置参数
元组,个数可变的位置参数只能是一个
def funn1(*args):
print(args)
print(args[0])
funn1(10)
funn1(10, 20)
funn1(10, 20, 30)
个数可变的关键字形参
字典,个数可变的关键字参数只能是一个
def funn2(**args):
print(args)
funn2(a=10)
funn2(a=10, b=20, c=30)
函数的调用
def funnn(a, b, c):
print('a=', a)
print('b=', b)
print('c=', c)
funnn(10, 20, 30) # 函数调用时的参数传递,称之为位置传参
lst = [11, 22, 33]
funnn(*lst) # 在函数调用时,将列表中的每个元素都转换为位置实参传入
funnn(a=100, b=300, c=200)
dic = {'a': 111, 'b': 222, 'c': 333}
funnn(**dic) # 在函数调用时,将字典中的键值对都转换为关键字实参传入
函数的定义
def funnn1(a, b=10):
print('a=', a)
print('b=', b)
def funnn2(*args):
print(args)
def funnn3(**args2):
print(args2)
funnn2(10, 20, 30, 40)
funnn3(a=11, b=22, c=33, d=44, e=55)
def funnn4(a, b, c, d):
print('a=', a)
print('b=', b)
print('c=', c)
print('d=', d)
# 调用funnn4
# global 声明全局变量
# nonlocal 声明外层的局部变量
funnn4(10, 20, 30, 40) # 位置实参传输
funnn4(a=10, b=20, c=30, d=40) # 关键字实参传递
funnn4(10, 20, c=30, d=40) # 前两个参数,采用位置实参传递,而c,d采用的是关键字实参传递
#需求,c,d只能采用关键字传递实参传递
def funnn5(a, b, *, c, d): # *的作用从*之后的参数,在函数调用时,只能采用关键字参数传递
print('a=', a)
print('b=', b)
print('c=', c)
print('d=', d)
funnn5(a=10, b=20, c=30, d=40)
funnn5(10, 20, c=30, d=40)
def funnn6(a, b, *, c, d, **args):
pass
def funnn7(*args, **args2):
pass
def funnn8(a, b, *args, **args2):
pass
def fuun(a, b):
c = a + b # c为局部变量,c在函数内定义的变量,a,b为函数的形参,作用范围也是函数内部,相当与局部变量
print(c)
name = '123' # name为全局变量,函数内部和外部都可以使用
print(name)
def fuun1():
print(name)
fuun1()
def fuun2():
global age # 局部变量使用global声明,这个变量实际上就变成了全局变量
age = 20
print(age)
fuun2()
print(age)
递归函数
def fac(n):
if n == 1:
return 1
else:
res = n * fac(n - 1)
return res
print(fac(6))
def fib(n):
if n == 1:
return 1
elif n == 2:
return 1
else:
return fib(n - 1) + fib(n - 2)
# 斐波那契数列
print(fib(6))
for i in range(1, 7):
print(fib(i))
字典函数和反射机制
本质上是python的反射机制
- hasattr() 判断 hasattr(obj, 'name')
- getattr() 获取执行 getattr(obj, 'name', ’errormsg)
- setattr() 赋值 setattr(obj, 'name', '李白')
- delattr() 删除 delattr(obj, 'name')
def yellow():
print("yellow")
def main():
dic={"黄色":yellow}
key=input("黄色")
dic[key]()
main()
class Yellow:
def yellow():
print('yellow')
def yellowc():
print('黄色')
def interact(self):
opt = input('黄色')
getattr(self, opt, self.warning)()
def warning(self):
print('输入错误')
obj = Yellow()
obj.interact()
lambda表达式和匿名函数
lambda arg1,arg2,arg3……:<表达式>
类/ 对象
面向对象的三大特征:
- 封装:提高程序的安全性
- 继承:提高代码的复用性
- 多态:提高程序的可扩展性和可维护性
类 / 数据类型:
不同的数据类型属于不同的类
使用内置函数type查看数据类型
对象 / 实例:
100、99、88都是int类之下包含的相似的不同个例
Python一切皆对象
对象包含,id(储存空间)、类型、值
元类-->实例化-->类(Human)-->实例化-->对象(obj)
类
使用class关键字定义的类,都是由内置元类type,实例化产生的
class Student: # Student为类名 由一个或多个单词组成,每个单词的首字母大写,其余小写
pass
print(id(Student))
print(type(Student))
print(Student)
'''类的组成类属性实力方法静态方法类方法'''
class Studentt:
native_pace = '吉林' # 直接写在类里的变量,称之为类属性
# 实力方法,在类之外成为函数,在类之内成为方法
def eat(self):
print('学生在吃饭。。。')
# 初始化方法
def __init__(self, name, age):
self.name = name # self.name 称之为实体属性,进行了一个赋值的操作,将局部变量的name的值赋给实体属性
self.age = age
# 静态方法,不使用self
@staticmethod
def method():
print('我使用了statticmethod进行修饰,所以我是静态方法')
# 类方法
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod进行修饰')
def drink():
print('喝水')
元类
元类:实例化产生类的类
print(type(Human))查看类的元类
# 造类bu
# 1.设置类名
class_name = 'Human'
# 2.设置基类
class_bases = (object,)
# 3.执行类子代码,产生命名空间,定义阶段执行,执行类子代码,产生命名空间
class_dic = {}
class_body = '''
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print('name:',self.name,'age:',self.age)
'''
# exec(要执行的代码,全局名称空间, 类名称空间)
exec(class_body, {}, class_dic)
# 4.调用元类
Human = type(class_name, class_bases, class_dic)
obj = Human('sj', 18)
obj.info()
自定义元类
# 只有继承type的类称为元类
class Mytype(type):
# __init__()内的参数指向(Human,Human,object,文档解释)
def __init__(self,class_name,class_bases,class_dic):
if '_' in class_name:
# 主动抛出异常
raise NameError('类名不能有下划线')
if not class_dic.get('__doc__'):
raise SyntaxError('定义类必须写注释')
# 调用类的第一步自动触发
# __new__()内的参数指向(Mytype本身,args就是class机制第四步传入的参数,kwargs和args相似)
def __new__(cls, *args, **kwargs):
# 可以自定义创建内容
return super().__new__(cls, *args, **kwargs)
class Human(object, metaclass = Mytype):
'''
这是文档解释
'''
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print('name:',self.name,'age:',self.age)
obj = Human('sj', 18)
print(obj)
手动传出参数
call__函数,内会自动调用__new() ,init()
# 只有继承type的类称为元类
class Mytype(type):
# 传出内置函数
# __call__()内的参数指向(Human本身,args调用Human时传入的参数,kwargs和args相似)
def __call__(self, *args, **kwargs):
human_obj = self.__new__(self)
self.__init__(human_obj, *args, **kwargs)
return human_obj
class Human(object, metaclass = Mytype):
'''
这是文档解释
'''
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print('name:',self.name,'age:',self.age)
def __new__(cls, *args, **kwargs):
# 这里找到的是object的new方法
obj = super().__new__(cls)
# 可以自定义
return obj
# 用于定义obj()的执行方案
def __call__(self, *args, **kwargs):
pass
obj = Human('sj', 18)
print(obj)
属性查找
向上查找为元类,横向查找 为父类
通过对象找属性,只会在父类里边找,不会去元类里边找
通过类找属性,会先在父类里边寻找找不到,会去元类里边寻找
类的浅拷贝和深拷贝
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
# 变量的赋值(类对象的赋值操作)
cpu1 = CPU()
cpu2 = cpu1
print(cpu1, id(cpu1))
print(cpu2, id(cpu2))
浅拷贝
# 只拷贝原对象
disk = Disk()
coputer = Computer(cpu1, disk)
import copy
print(disk)
coputer2 = copy.copy(coputer)
print(coputer, coputer.cpu, coputer.disk)
print(coputer2, coputer2.cpu, coputer.disk)
深拷贝
# 拷贝原对象和子对象
coputer3 = copy.deepcopy(coputer)
print(coputer, coputer.cpu, coputer.disk)
print(coputer3, coputer3.cpu, coputer3.disk)
对象
print(type(obj))查看对象的类型。
class Studennt:
native_pace = '吉林' # 直接写在类里的变量,称之为类属性
# 实力方法,在类之外成为函数,在类之内成为方法
def eat(self):
print('学生在吃饭。。。')
# 初始化方法
def __init__(self, name, age):
self.name = name # self.name 称之为实体属性,进行了一个赋值的操作,将局部变量的name的值赋给实体属性
self.age = age
# 静态方法,不使用self
@staticmethod
def method():
print('我使用了statticmethod进行修饰,所以我是静态方法')
# 类方法
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod进行修饰')
stu1 = Studennt('张三', 20)
print(id(stu1))
print(type(stu1))
print(stu1)
print('------------')
print(id(Studennt)) # 类的名称
print(type(Studennt))
print(Studennt)
class Studeent:
native_pace = '吉林' # 直接写在类里的变量,称之为类属性
# 实力方法,在类之外成为函数,在类之内成为方法
def eat(self):
print('学生在吃饭。。。')
# 初始化方法
def __init__(self, name, age):
self.name = name # self.name 称之为实体属性,进行了一个赋值的操作,将局部变量的name的值赋给实体属性
self.age = age
# 静态方法,不使用self
@staticmethod
def method():
print('我使用了statticmethod进行修饰,所以我是静态方法')
# 类方法
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod进行修饰')
stu1 = Studeent('张三', 20)
stu1.eat() # 对象名.方法名
print(stu1.name)
print(stu1.age)
print('------------')
stu2 = ('张三', 20)
Studeent.eat(stu2) # 121行与116行代码功能相同,都是调用Studeent中的eat方法
# 类名.方法名(类的对象)-->实际上就是方法定义处的self
print('------------')
class Studdent:
native_pace = '吉林' # 直接写在类里的变量,称之为类属性
# 实力方法,在类之外成为函数,在类之内成为方法
def eat(self):
print('学生在吃饭。。。')
# 初始化方法
def __init__(self, name, age):
self.name = name # self.name 称之为实体属性,进行了一个赋值的操作,将局部变量的name的值赋给实体属性
self.age = age
# 静态方法,不使用self
@staticmethod
def method():
print('我使用了statticmethod进行修饰,所以我是静态方法')
# 类方法
@classmethod
def cm(cls):
print('我是类方法,因为我使用了classmethod进行修饰')
# 类属性的定义方式
print("----------类属性----------")
print(Studdent.native_pace)
stu1 = Studdent('张三', 20)
stu2 = Studdent('李四', 20)
print(stu1.native_pace)
print(stu2.native_pace)
# 修改类属性吉林为天津
Studdent.native_pace = '天津'
print(stu1.native_pace)
print(stu2.native_pace)
类方法的使用
Studdent.cm()
静态方法的使用
Studdent.method()
动态绑定属性和方法
class Stuudent:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(self.name + '在吃饭')
stu1 = Stuudent('张三', 20)
stu2 = Stuudent('李四', 30)
动态绑定属性
stu1.gender = '女'
print(stu1.name, stu1.age, stu1.gender)
print(stu2.name, stu2.age)
动态绑定方法
stu1.eat()
stu2.eat()
def show():
print('定义在类之外的,称之为函数')
stu1.show = show # 可以在最后加括号同192行代码结果相同
stu1.show()
# stu2.show()
多态
class Animal(object):
def eat(self):
print('动物会吃')
class Dog(Animal):
def eat(self):
print('狗吃骨头')
class Cat(Animal):
def eat(self):
print('猫吃鱼')
class Person:
def eat(self):
print('人吃五谷杂粮')
def fun(obj):
obj.eat()
fun(Cat())
fun(Dog())
fun(Animal())
print('--------------------')
fun(Person())
类的使用示例
class Person:
a = 123456
def __init__(self):
self.name = None
self.age = None
def getALl(self):
return self.name + str(self.age)
def xmlToObj(self, xmlData):
pass
def objToXMl(self):
pass
class Student(Person):
def __init__(self):
super().__init__()
self.stuNo = None
self.className = None
def getALl(self):
return self.name + '覆盖'
class Worker(Person):
def __init__(self):
super().__init__()
if __name__ == '__main__':
person = Person()
person.name = '张三'
person.age = 18
print(person.name)
print(person.getALl())
student = Student()
student.name = '李四'
student.age = '20'
student.stuNo = '184613038'
student.className = '123'
print(student.getALl())
print(student.a)
xmlData = ''
student.xmlToObj(xmlData)
student.objToXMl()
继承
class Person(object): # Person继承object类
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name, self.age)
class Student(Person):
def __init__(self, name, age, stu_no):
super().__init__(name, age) # super()调用父类(Person)去给属性赋值,相当于从新写了一边45,46行代码
self.stu_no = stu_no
class Teacher(Person):
def __init__(self, name, age, teachofyear):
super().__init__(name, age) # super()调用父类(Person)去给属性赋值,相当于从新写了一边45,46行代码
self.teachofyear = teachofyear
stu = Student('张三', 20, '1001')
teacher = Teacher('李四', 34, 10)
stu.info()
teacher.info()
多继承
class A(object):
pass
class B(object):
pass
class C(A, B):
pass
# 子类输出
class Personn(object): # Person继承object类
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name, self.age)
class Studentt(Personn):
def __init__(self, name, age, stu_no):
super().__init__(name, age)
self.stu_no = stu_no
def info(self): # 重写父类的info,只能在Student中调用
super().info() # 调用父类之前的输出
print(self.stu_no)
class Teacherr(Personn):
def __init__(self, name, age, teachofyear):
super().__init__(name, age)
self.teachofyear = teachofyear
def info(self):
super().info()
print('教龄', self.teachofyear)
stu = Studentt('张三', 20, '1001')
teacher = Teacherr('李四', 34, 10)
stu.info()
teacher.info()
继承object类
class Studennt():
pass
stu = Studennt()
print(dir(stu)) # 继承object类的属性和方法
print(stu)
class Studeent:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '我的名字是{0},今年{1}岁'.format(self.name, self.age)
stu = Studeent('张三', 20)
print(dir(stu)) # 继承object类的属性和方法
print(stu) # 默认调用__str__()这个方法
print(type(stu))
使用类构造函数和垃圾回收
使用删除时进行调用
class Person:
def __del__(self):
print("销毁对象:{0}".format(self))
p1 = Person()
p2 = Person()
del p2
print("程序结束")
类内置初始函数
class Person():
__slots__ = ('name', 'age') # 限制属性,超出会报错
# 定义一个可调用对象,当对象被当作函数调用时执行
def __call__(self, *args, **kwds):
pass
# 返回对象的类,通常不需要重写
def __class__(self):
pass
# 析构方法,当对象被销毁时调用
def __del__(self):
pass
# 删除对象的属性
def __delattr__(self):
pass
# 返回对象的属性字典
def __dict__(self):
pass
# 返回对象的属性列表
def __dir__(self):
pass
# 返回对象的文档字符串
def __doc__(self):
pass
# 比较两个对象是否相等
def __eq__(self):
pass
# 格式化对象的字符串表示
def __format__(self):
pass
# 比较两个对象,当前对象是否大于等于另一个对象
def __ge__(self):
pass
# 获取对象的属性值
def __getattribute__(self):
pass
# 比较两个对象,当前对象是否大于另一个对象
def __gt__(self):
pass
# 返回对象的哈希值
def __hash__(self):
pass
# 初始化方法,当创建对象时调用
def __init__(self, *args, **kwargs):
pass
# 初始化子类
def __init_subclass__(cls, **kwargs):
pass
# 比较两个对象,当前对象是否小于等于另一个对象
def __le__(self):
pass
# 返回对象的长度
def __len__(self):
pass
# 比较两个对象,当前对象是否小于另一个对象
def __lt__(self):
pass
# 返回对象的模块名
def __module__(self):
pass
# 比较两个对象是否不相等
def __ne__(self):
pass
# 创建对象
def __new__(cls, *args, **kwargs):
pass
# 返回对象的序列化信息
def __reduce__(self, *args, **kwargs):
pass
# 返回对象的序列化信息,带协议版本
def __reduce_ex__(self):
pass
# 返回对象的字符串表示
def __repr__(self):
pass
# 设置对象的属性值
def __setattr__(self):
pass
# 返回对象的大小
def __sizeof__(self):
pass
# 返回对象的非正式字符串表示
def __str__(self):
pass
# 用于判断类是否是子类的钩子函数
def __subclasshook__(cls, subclass):
pass
# 返回对象的弱引用
def __weakref__(self):
pass
# __str__
# 使用打印的使进行调用
class Human():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
print('__str__运行了')
return f'<{self.name}:{self.age}>'
obj = Human('sj',18)
print(obj)
## __call__
class SalaryAccount:
def __call__(self, salary):
print('算工资了')
yearSalary = salary * 12
daySalary = salary // 22.5
hourSalary = daySalary // 8
return dict(yearSalary=yearSalary,
monthSalary=salary, daySalary=daySalary,
hourSalary=hourSalary)
s = SalaryAccount()
print(s(30000))
## __dict__
class A:
pass
class B:
pass
class C(A, B):
def __init__(self, name, age):
self.name = name
self.age = age
class D(A):
pass
x = C('Jack', 20) # 创建C类对象 x是C类型的实力对象
print(x.__dict__) # 实例对象的属性字典
print(C.__dict__)
print('----------------------')
print(x.__class__) # 输出的是对象所属的类
print(C.__bases__) # 输出的是C类的父类元组
print(C.__base__) # 输出的是第一个C类的父类
print(C.__mro__) # 输出的是类的一个层次结构
print(A.__subclasses__()) # A的子类的列表
## __len__() 通过重写__len__()方法,让内置函数len()的参数可以是自定义类型
## __add__() 通过重写__add__()方法,可以使用自定义对象具有"+"功能
## __new__() 用于创建对象
## __init__() 对创建的对象进行初始化
a = 20
b = 100
c = a + b # 两个整数类型的对象的相加操作
d = a.__add__(b)
print(c)
print(d)
class Studdent:
def __init__(self, name):
self.name = name
def __add__(self, other): # 使两个对象具有相加的能力
return self.name + other.name
def __len__(self):
return len(self.name)
stu1 = Studdent('张三')
stu2 = Studdent('李四')
s = stu1 + stu2 # 实现了两个对象的加法运算(因为在Studdent类中编写__add__()特殊的方法)
print(s)
s = stu1.__add__(stu2)
print(s)
print('-----------------------')
lst = [11, 22, 33, 44]
print(len(lst))
print(lst.__len__())
print(len(stu1))
class Person(object):
def __new__(cls, *args, **kwargs):
print('__new__被调用执行了,cls的id值为{0}'.format(id(cls)))
obj = super().__new__(cls)
print('创建的对象的id为:{}'.format(id(obj)))
return obj
def __init__(self, name, age):
print('__init__被调用了,self的id值为:{0}'.format(id(self)))
self.name = name
self.age = age
print('object这个类对象的id为:{0}'.format(id(object)))
print('Person这个类对象id为:{0}'.format(id(Person)))
# Person类的实例对象p1
p1 = Person('张三', 20)
print('p1这个Person类的实例对象的id:{0}'.format(id(p1)))
property无重载,方法动态性
类方法使用property
class Person:
def work(self):
print('努力上班!')
def play_game(s):
print('{0}在玩游戏'.format(s))
def work2(s):
print('好好工作,努力上班!赚大钱,娶媳妇!')
Person.play = play_game
p = Person()
p.work()
p.play()
Person.work = work2
p.work()
装饰器方法使用property
- 只能用来装饰get方法
- 被装饰的属性前面不需要在使用get或set方法做前缀
- 在装饰set方法时,要保证set方法和get方法名同名,先装饰get方法,然后使用@get方法名.setter形式装饰set方法
这样做的好处就是可以将set方法和get方法命名为同一个名字,直接当做属性进行使用即可。
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
@property
def salary(self):
return self.__salary
@salary.setter
def salary(self,salary):
if 1000 < salary < 5000:
self.__salary = salary
else:
print('错误')
emp1 = Employee('张三', 3000)
print(emp1.salary)
emp1.salary = 2000
print(emp1.salary)
设计模式
实现分离
工厂模式
class CarFactory:
def create_car(self,brand):
if brand == '奔驰':
return Benz()
elif brand == '宝马':
return BMW()
elif brand == '比亚迪':
return BYD()
else:
return '未知品牌,无法创建'
class Benz:
pass
class BMW:
pass
class BYD:
pass
factory = CarFactory()
c1 = factory.create_car('奔驰')
c2 = factory.create_car('比亚迪')
print(c1)
print(c2)
单例模式
有需要频繁和销毁对象的过程,针对性优化
-
模块导入
|--tree |-- main.py |--utls.py |--test2.pyutls.py
class Human: def __init__(self,name,age): self.name = name self.age = age obj = Human('sj',18)main.py
from utls import obj -
类装饰器
def singleton_mode(cls): obj = None def wrapper(*args, **kwargs): nonlocal obj if not obj: obj = cls(*args, **kwargs) return obj return wrapper @singleton_mode class Human: def __init__(self,name,age): self.name = name self.age = age obj = Human('sj',18) -
类绑定方法
class Human: obj = None def __init__(self,name,age): self.name = name self.age = age @classmethod def get_obj(cls, *args, **kwargs): if not cls.obj: cls.obj = cls(*args, **kwargs) return cls.obj obj = Human.get_obj('sj',18) -
__new__方法
# 一 class Human: obj = None def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if not cls.obj: cls.obj = super().__new(cls) return cls.obj obj = Human('sj',18) # 二 class MySingleton: __obj = None __init_flag = True def __new__(cls, *args, **kwargs): if cls.__obj == None: cls.__obj = object.__new__(cls) return cls.__obj def __init__(self, name): if MySingleton.__init_flag: self.name = name MySingleton.__init_flag = False a = MySingleton('aa') b = MySingleton('bb') print(a) print(b) -
元类
class Mytype(type): obj = None def __call__(self, *args, **kwargs): if not self.obj: # self.obj = super().__call__(*args, **kwargs) self.obj = self.__new__(self) self.__init__(self.obj, *args, **kwargs) return self.obj class Human: obj = None def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kwargs): if not cls.obj: cls.obj = super().__new(cls) return cls.obj obj = Human('sj',18) -
并发
((20240103011410-ztl2ydn '进程线程协程'))
封装
class Car:
def __init__(self, brind):
self.brand = brind
def start(self):
print('汽车已启动。。。')
car = Car('宝马X5')
car.start()
print(car.brand)
class Student:
def __init__(self, name, age):
self.name = name
self.__age = age
def show(self):
print(self.name, self.__age)
stu = Student('张三', 20)
stu.show()
print(stu.name)
# print(stu.__age)
# print(dir(stu)) # 查看stu实例调用Student中的形式参数
print(stu._Student__age) # 在类的外部可以通过 _类名__实力属性,进行访问私例

浙公网安备 33010602011771号