1 类中的方法
1.1 实例方法
- 实例方法描述的是对象的行为,声明在类型中,只能通过对象调用
- 可以访问属性数据和对象数据
class Emperor:
# 实例方法
def find(self):
print("两处茫茫皆不见")
li = Emperor()
li.find() # 两处茫茫皆不见
1.2 类方法
- 类方法是声明在类型中的方法,使用@classmethod 装饰
- 类方法的第一个参数是当前类型cls(约定俗成使用cls,可以使用其他名称)
- 类方法只能访问类型属性,不能访问实例属性
- 可以通过类型名称和对象引用直接调用
class Master:
content = "为感君王辗转思,遂教方士殷勤觅。"
@ classmethod
def call(cls):
print("临邛道士鸿都客,能以精诚致魂魄。", end="")
# 获取类属性需要在前面加cls.
print(cls.content)
# 类型名称调用
Master.call() # 临邛道士鸿都客,能以精诚致魂魄。为感君王辗转思,遂教方士殷勤觅。
# 对象引用调用
master = Master
master.call() # 临邛道士鸿都客,能以精诚致魂魄。为感君王辗转思,遂教方士殷勤觅。
1.3 静态方法
- 类型中的普通函数,使用@staticmethod 装饰器声明
- 不能访问实例属性,不能访问类型属性
class Master:
@ staticmethod
def find():
print("为感君王辗转思,遂教方士殷勤觅")
Master.find() # 为感君王辗转思,遂教方士殷勤觅
1.3 访问范围(边界判断)
方法名称 | 实例方法 | 类方法 | 静态方法 |
---|---|---|---|
实例属性数据 | 是 | 否 | 否 |
类属性数据 | 是 | 是 | 否 |
局部变量数据 | 是 | 是 | 是 |
2 反射操作
- 反射是在程序运行过程中,动态的从内存中获取执行状态,根据执行状态动态调用执行,完成具体功能的操作
- 反射不直接操作对象数据,而是通过字符串的对象描述,交给运行中的程序,程序在运行时获取到字符串描述的对象数据,再去执行对象数据的操作,类比eval()函数
- 反射可用于调试或容错开发(不确定目标对象是否已经完善了对应的函数/方法,但可以直接调用执行并且保证程序不能出错)
反射方法(内建函数):
- hasattr(obj, name) 查询对象 obj 中是否有属性 name
- getattr(obj, name) 获得对象 obj 中属性 name
- setattr(obj, name, value) 设置对象 obj 中属性 name
- delattr(obj, name) 删除对象 obj 中属性 name
class Emperor:
def __init__(self, name):
self.name = name
def search(self, obj):
# 用反射判断是否存在对应的方法,输出不同结果
# 查询属性
if hasattr(obj, "like"):
# 获取属性
res = getattr(obj, "like")
return res()
else:
print("排空驭气奔如电,升天入地求之遍。上穷碧落下黄泉,两处茫茫皆不见。")
class Consort:
def __init__(self, name):
self.name = name
def like(self):
print("楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。")
class Person:
pass
# 创建对象
li = Emperor("李隆基")
yang = Consort("杨玉环")
per = Person()
# 根据反射条件返回结果
li.search(per) # 排空驭气奔如电,升天入地求之遍。上穷碧落下黄泉,两处茫茫皆不见。
li.search(yang) # 楼阁玲珑五云起,其中绰约多仙子。中有一人字太真,雪肤花貌参差是。
# 修改
setattr(li, "name", "唐玄宗")
print(li.name) # 唐玄宗
# 新增(不推荐在类型定义外新增属性)
setattr(li, "age", 52)
print(li.age) # 52
# 删除
delattr(li, "age")
print(li.age) # 报错 'Emperor' object has no attribute 'age'
3 单例模式
3.1 设计模式
- 又称软件设计模式
- 是一套被反复使用、经过分类编目的代码设计经验总结
- 可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性
- 成熟设计模式有20多种
3.2 单例模式
- 单例模式是设计模式中创建型模式的一种
- 指项目中某些数据,只能出现一次(如某个类只能能有一个实例)
class Emperor:
_emperor = None
def __new__(cls, *args, **kwargs):
if not cls._emperor:
cls._emperor = object.__new__(cls) # 不存在则创建
return cls._emperor
def __init__(self, name): # 每次执行创建初始化仍然回执行,但都是同一个对象
self.name = name
emp1 = Emperor("李隆基")
print(emp1.name) # 李隆基
emp2 = Emperor("唐玄宗")
print(emp2.name) # 唐玄宗
emp3 = Emperor("唐明皇")
print(emp3.name) # 唐明皇
# 虽然有三个引用变量,但是id是一样的,即始终是同一个对象
print(id(emp1), id(emp2), id(emp3)) # 2178250177224 2178250177224 2178250177224
# 打印出来都是最后一次修改的属性
print(emp1.name, emp2.name, emp3.name) # 唐明皇 唐明皇 唐明皇
如果只需执行一次初始化:
class Emperor:
_emperor = None
# 是否已经初始化的标记
init_note = False
def __new__(cls, *args, **kwargs):
if not cls._emperor:
cls._emperor = object.__new__(cls) # 不存在则创建
return cls._emperor
def __init__(self, name):
# 判断是否已经初始化,如果已经未初始化则进行初始化
if Emperor.init_note is False:
self.name = name
# 初始化后修改标记
Emperor.init_note = True
# 如果已经初始化则不执行初始化并直接返回
else:
return
emp1 = Emperor("李隆基")
print(emp1.name) # 李隆基
emp2 = Emperor("唐玄宗")
print(emp2.name) # 唐玄宗
emp3 = Emperor("唐明皇")
print(emp3.name) # 唐明皇
# 只有第一次创建对象时初始化
print(emp1.name, emp2.name, emp3.name) # 李隆基 李隆基 李隆基