昨日回顾
类的绑定方法
classmethod(类的绑定方法)
翻译过来是一个类方法,是一个装饰器,可以装饰给类内部的方法,使该方法绑定给类来使用。
--- 对象的绑定方法的特殊之处:由对象来调用,会将对象当作第一个参数传给该方法
--- 类的绑定方法的特殊之处:由类来调用,会将类仿作第一个参数传给该方法
通过对象也可以调用,只是默认传递的第一个参数还是这个对象对应的类
staticmethod(非绑定方法)
是一个装饰器,可以装饰类内部的方法,使该方法即不绑定给对象,也不绑定给类。谁都可以调用,且没有自动传值的效果
简而言之,非绑定方法就是将普通方法放到类的内部
总结
如果函数体代码需要用外部传入的类,则应该将函数定义成绑定给类的方法
如果函数体代码需要用外部传入的对象,则应该将函数定义成绑定给对象的方法
如果函数体代码即不需要外部传入的类,也不需要外部传入的对象,则应该将该函数定义成非绑定方法/普通函数
面向对象高阶
isinstance
python内置的函数,用来传入两个参数,用于判断参数1是否是参数2的一个实例。
判断一个对象是否使一个类的实例,打印结果使True或者使False
print(isinstance(obj,class))
issubclass
python内置的函数,可以传入两个的参数,用于判断参数1是否使参数2 的子类。
判断一个类是否是另一个类的子类,打印结果使True或者使False
print(issubclass(子类,父类))
反射(*******************)
反射指的是通过 ’字符‘串’ 对 对象或者类的属性进行操作
-- hasattr:通过字符串,判断该字符串是否使对象或类的属性
print(hasattr(对象或者类,'属性'))
-- getattr:通过字符串,获取对象或类的属性
print(getattr(o,name,default))
-- setattr:通过字符串,设置对象或类的属性
setattr(p,'sal','3.0')
print(hasattr(p,'sal')) # True
-- delattr:通过字符串,删除对象或类的属性。
delattr(p,'sal')
print(hasattr(p,'sal'))
魔法方法(类的内置方法)
凡是在类内部定义,以"__开头__结尾"的方法都称之为魔法方法,又称“类的内置方法”。
魔法方法会在某些条件成立时触发。
__str__:在打印对象时触发
__def__:对象被销毁前执行该方法,该方法会在最后执行
__getattr__:会在对象.属性时,“属性没有”的情况下才会触发
__setattr__:会咋“对象.属性 = 属性值”时触发
__call__:会砸对象你被调用时触发
__new__:会在__init__执行前触发
__init__:在调用类时触发
关于对__new__与__init__的理解在定义的类中,__new__是自动运行的,而且是隐藏起来的,当调用类进行实例化的时候,__new__与__init__一样是自动运行的,但是区别是__new__运行之后是产生一个空的对象的名称空间,然后__init__的作用是对这个产生的空的名称空间进行修饰。__new__后边跟的是(cls),指的是类,在执行的时候,传入的第一个对象是类,而__init__后边跟着的是(self),指的是对象,在执行的时候传入的第一个对象是对象本身。所以在运行 __init__的时候,其实是运行了__new___和__init__,一个负责搭建空的对象的名称空间,一个负责对这个空的名称空间进行装饰,也就是将__init__中的参数值添加到所产生的名称空间内。然而,当自己定义一个__new__的时候,会先执行自己定义的这个__new__,但是记住一定要记住最后一步一定要返回 object.__new__(cls),作用是来调用来调用object类中的__new__来产生一个空的名称空间,不然下边的__init__没有办法执行来对空的对象的名称空间进行修饰,因为就没有产生对象的名称空间.
class Foo(object):
#
def __new__(cls, *args, **kwargs):
return object.__new__(cls) # 真正产生一个空对象
# 若当前类的__new__没有return一个空对象时,则不会触发。
def __init__(self):
print('在调用类时触发...')
def __str__(self):
print('会在打印对象时触发...')
# 必须要有一个返回值, 该返回值必须时字符串类型
return '[1, 2, 3]'
def __del__(self):
print('对象被销毁前执行该方法...')
def __getattr__(self, item):
print('会在对象.属性时,“属性没有”的情况下才会触发...')
print(item)
# 默认返回None, 若想打印属性的结果,必须return一个值
return 111
# 注意: 执行该方法时,外部“对象.属性=属性值”时无效。
def __setattr__(self, key, value):
print('会在 “对象.属性 = 属性值” 时触发...')
print(key, value)
print(type(self))
print(self, 111)
self.__dict__[key] = value
def __call__(self, *args, **kwargs):
print(self)
print('调用对象时触发该方法...')
#
foo_obj = Foo()
print(foo_obj)
print(foo_obj.x)
print(foo_obj.x)
foo_obj.x = 123
print(foo_obj.x)
foo_obj()
单例模式
在类中,在调用一次类,就会进行一次类的实例化,就会产生一个对象的名称空间,再次调用的时候,会继续产生新的名称空间,在调用相同的文件的时候也是会产生不同的名称空间,这样的话比较浪费内存,所以就想对同一个文件打开的时候,对应的名称空间是同一个,方法如下:
class File:
__instance = None
# 单例方式1:
# @classmethod
# def singleton(cls, file_name):
# if not cls.__instance:
# obj = cls(file_name)
# cls.__instance = obj
# return cls.__instance
# 单例方式2:
def __new__(cls, *args, **kwargs):
# cls.__new__(cls, *args, **kwargs)
if not cls.__instance:
cls.__instance = object.__new__(cls)
print(cls.__instance)
return cls.__instance
def __init__(self, file_name, mode='r', encoding='utf-8'):
self.file_name = file_name
self.mode = mode
self.encoding = encoding
def open(self):
self.f = open(self.file_name, self.mode, encoding=self.encoding)
def read(self):
res = self.f.read()
print(res)
def close(self):
self.f.close()
# 方式1:
# obj1 = File.singleton('jason雨后的小故事.txt') # singleton(cls)
# obj2 = File.singleton('jason雨后的小故事.txt') # singleton(cls)
# obj3 = File.singleton('jason雨后的小故事.txt') # singleton(cls)
# obj1 = File('jason雨后的小故事.txt')
# obj2 = File('jason雨后的小故事.txt')
# obj3 = File('jason雨后的小故事.txt')
# print(obj1)
# print(obj2)
# print(obj3)
# 方式2:
obj1 = File('jason雨后的小故事.txt') # singleton(cls)
obj2 = File('jason雨后的小故事.txt') # singleton(cls)
obj3 = File('jason雨后的小故事.txt') # singleton(cls)
print(obj1)
print(obj2)
print(obj3)