目录
类的绑定方法
classmethod
-
是一个装饰器,可以装饰给类内部的方法,使该方法绑定给类来使用
-
由类来调用类中定义的函数称之为类的绑定方法,该函数会绑定给类使用,并且会将类当做该绑定方法的第一个参数自动传入
class People: def __init__(self,name,age): self.name = name self.age = age @classmethod #先使用装饰器默认添加函数参数 "cls" def prt_info(cls): print(f'''姓名: {cls('蔡启龙',25).name} 年龄: {cls('蔡启龙',25).age}''') People.prt_info() print('*'*50) people = People('tank',30) people.prt_info() #类的绑定方法也可以由对象调用,默认将该对象的类当做第一个参数传入绑定方法 ''' 姓名: 蔡启龙 年龄: 25 ************************************************** 姓名: 蔡启龙 年龄: 25 '''
import user_info_settings
class Teacher:
def __init__(self,username,pwd):
self.username = username
self.pwd = pwd
#主页
def index(self):
if self.username == '蔡启龙' and self.pwd == '123':
print('验证通过,显示主页')
# 用户保存登录信息,提供自动登录接口
@classmethod
def login_auth(cls):
obj = cls(user_info_settings.username,user_info_settings.pwd)
obj.index()
teacher = Teacher('蔡启龙','123')
teacher.index()
print('*'*16)
Teacher.login_auth() #调用自动登录接口
'''
验证通过,显示主页
****************
验证通过,显示主页
'''
非绑定方法
staticmethod
-
是一个装饰器,可以装饰给类内部的方方法,使该方法既不绑定给类,也不绑定给对象
import uuid # 一个加密模块,其中的uuid4()方法可以通过时间戳生成一个世界上唯一的字符串 import hashlib class Teacher: @staticmethod def creat_id(): uuid_obj = uuid.uuid4() # 返回值是一个对象 m = hashlib.md5() m.update((str(uuid_obj).encode('utf-8'))) print(m.hexdigest()) Teacher.creat_id() # 类调用非绑定方法 teacher = Teacher() teacher.creat_id() # 对象调用非绑定方法
isinstance和issubclass
判断一个对象是否是一个类的实例---isinstance
-
isinstance('参数1','参数2')
-
python内置的函数,可以传入两个参数,用于判断参数1是否是参数2的一个实例
class Foo: pass class Goo: pass foo = Foo() print(foo.__class__) # "__class__" 是对象的属性,获取对象所属的类 print(isinstance(foo, Foo)) # True print(isinstance(foo, Goo)) # False
-
判断一个类是否是另一个类的子类---issubclass
-
python内置函数,可以传入两个参数,用于判断参数1是否是参数2的子类
class Foo: pass class Goo(Foo): pass class Hoo: pass print(issubclass(Goo, Foo)) # True print(issubclass(Hoo, Foo)) # False
反射
什么是反射?
- 通过 "字符串" 对 对象或类的属性进行操作
反射的四种方法
-
hasattr---查
-
通过字符串,判断该字符串是否是对象或类的属性
class People: country = 'China' def __init__(self, name): self.name = name people = People('蔡启龙') # 普通方式 print('name' in people.__dict__) # True print('country' in People.__dict__) # True print('country2' in People.__dict__) # False # hasattr print(hasattr(people, 'name')) # True
-
-
getattr
-
通过字符串,获取对象或类的属性
class People: country = 'China' def __init__(self, name): self.name = name people = People('蔡启龙') # 普通方式 print(people.__dict__.get('name', 'tank')) print(people.__dict__.get('score', 99)) # getattr print(getattr(people, 'country', 'Japan')) print(getattr(People, 'country2', 'Japan')) ''' 蔡启龙 99 China Japan '''
-
-
setattr---改
-
通过字符串,修改对象或类的属性
class People: country = 'China' def __init__(self, name): self.name = name people = People('蔡启龙') # 普通方式 people.score = '100' print(getattr(people, 'score', 99)) # setattr setattr(people, 'country', 'America') print(getattr(People, 'country')) print(getattr(people, 'country')) ''' 100 China America '''
-
-
delattr---删
-
通过字符串,删除对象或类的属性
class People: country = 'China' def __init__(self, name): self.name = name people = People('蔡启龙') # 普通方式 del people.name print(hasattr(people, 'name')) # False # delattr delattr(People, 'country') print(hasattr(People, 'country')) # False
-
反射小练习
class Movie: def input(self): while True: cmd = input('请输入执行的方法名:').strip() # 判断用户指令是否存在 if hasattr(self, cmd): method = getattr(self, cmd) method() else: print('命令错误,请重新输入') def upload(self): print('电影开始上传...') def download(self): print('电影开始下载...') movie_obj = Movie() movie_obj.input()
-
类的内置方法(魔法方法)
什么是类的魔法方法?
- 在类的内部定义,以
__开头__结尾
的方法称为类的魔法方法,又称类的内置方法 - 类的魔法方法会在默写条件成立时立即触发(调用)
常用的类的魔法方法
-
__init__
: 在调用类时触发,用来给空对象初始化属性 -
__str__
: 打印对象时触发class Foo: # 该方法必须要有一个字符串数据类型的返回值,否则报错:TypeError: __str__ returned non-string (type NoneType) def __str__(self): print('打印对象时触发') return '__str__测试' # 不使用该魔法方法打印对象时输出的结果是对象地址 obj = Foo() print(obj) ''' 打印类象时触发 __str__测试 '''
class MyList: def __init__(self, lt): self.lt = lt def __str__(self): return str(self.lt) lt = MyList([1, 2, 3]) print(lt) # [1, 2, 3]
-
__del__
: 在程序执行结束,对象被销毁前执行该方法class Foo: def __del__(self): print('对象被销毁前执行该方法') obj = Foo() print('程序执行完毕,准备销毁对象') ''' 程序执行完毕,准备销毁对象 对象被销毁前执行该方法 '''
-
__getattr__
: 在对象.属性
,属性没有时触发class Foo: # 默认返回None,若想打印属性的结果,必须return一个值 def __getattr__(self, item): print('__getattr__测试', f',没有的属性为{item}') return '__getattr__的返回值' obj = Foo() print(obj.x) ''' __getattr__测试 ,没有的属性为x __getattr__的返回值 '''
-
__getattribute__
: 在对象.属性
, 无论属性有没有, 都会触发 -
__setattr__
: 在对象.属性 = 属性值
时触发class Foo: def __setattr__(self, key, value): print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}') obj = Foo() obj.x = 10 print('*' * 50) ''' 在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10 ************************************************** '''
class Foo:
def __setattr__(self, key, value):
print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
self.__dict__[key] = value
obj = Foo()
obj.x = 10
print('*' * 50)
print(obj.x)
'''
在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10
**************************************************
10
'''
class Foo:
# 执行该方法时,外部 "对象.属性 = 属性值" 无效
def __setattr__(self, key, value):
print(f'在 `对象.属性 = 属性值` 时触发,属性名为:{key},属性值为{value}')
def __getattr__(self, item):
print('__getattr__测试', f',没有的属性为{item}')
obj = Foo()
print(obj.x, '
', '*' * 30)
obj.x = 10
print(obj.__dict__, '
', '*' * 30)
print(obj.x, '
', '*' * 30)
'''
__getattr__测试 ,没有的属性为x
None
******************************
在 `对象.属性 = 属性值` 时触发,属性名为:x,属性值为10
{}
******************************
__getattr__测试 ,没有的属性为x
None
******************************
'''
-
__call__
: 在对象被调用时触发class Foo: def __call__(self, *args, **kwargs): print(f'{self},调用对象时触发') obj = Foo() obj() # <__main__.Foo object at 0x000001A275CDD278>,调用对象时触发
-
__new__
: 在__init__
执行前触发,用来生成一个空对象class Foo: # 真正用来生成一个空对象,需要通过return才能将空对象返回出去. def __new__(cls, *args, **kwargs): print(cls) return object.__new__(cls) # 给空对象初始化属性,若当前类的__new__方法没有return一个空对象,则不会触发. def __init__(self): print('初始化空对象时调用') obj = Foo() ''' <class '__main__.Foo'> 初始化空对象时调用 '''
类的魔法方法 __del__
的应用
-
class MyOpen: def __init__(self, filename, mode='r', encoding='utf-8'): self.filename = filename self.mode = mode self.encoding = encoding # 句柄:一种特殊的只能指针引用对象或内存块时候使用 def file_open(self): self.f = open(self.filename, self.mode, encoding=self.encoding) # 产生句柄并当做属性添加到实例化出的对象中 def file_read(self): res = self.f.read() print(f'''当前文件名称: {self.filename} 当前文件数据: {res}''') def __del__(self): self.f.close() print('文件关闭成功') openmyfile = MyOpen('蔡启龙雨后的小故事') openmyfile.file_open() openmyfile.file_read() print('程序执行结束,准备销毁对象')
单例模式
什么是单例模式
- 实例化多个对象会产生不同的内存地址
- 单例模式可以使每次实例化产生的对象都使用同一个地址
- 例如打开文件的操作
单例模式的目的
- 减少内存占用
如何实现
-
''' 从配置文件中获取相同的文件名的数据 ''' class MyOpen: __instance = None # 访问限制机制 # 单例方式一: # 类的绑定方法 @classmethod def singleton(cls, filename): if not cls.__instance: obj = cls(filename) cls.__instance = obj return cls.__instance # 单例方式二: # 魔法方法__new__ def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance def __init__(self, filename, mode='r', encoding='utf-8'): self.filename = filename self.mode = mode self.encoding = encoding def open(self): self.f = open(self.filename, self.mode, encoding=self.encoding) def read(self): res = self.f.read() print(res) def close(self): self.f.close() # obj1 = MyOpen.singleton('蔡启龙雨后的小故事.txt') # obj2 = MyOpen.singleton('蔡启龙雨后的小故事.txt') # print(obj1) # print(obj2) obj3 = MyOpen('蔡启龙雨后的小故事.txt') obj4 = MyOpen('蔡启龙雨后的小故事.txt') print(obj3) print(obj4)