面向对象进阶
类方法和静态方法
类方法和实例(静态)方法
类方法
@classmethod
def clsmtd(cls):
print(xxx)
a = MyClass()
a.clsmtd()是可以调用的, 等同于a.__class__.clsmtd()
- 在类定义中,使用@classmethod装饰器修饰的方法
- 必须至少有一个参数,且第一个参数就给了cls,cls指调用者就是对象自己
- cls可以是任意合法名称,但是为了易读性,不要改
- 通过cls可以直接操作类的属性,但是无法通过cls操作类的实例
静态方法(非绑定方法)
@staticmethod
def staticmtd():
print('static')
- 在类的定义中,使用@staticmethod装饰器修饰的方法
- 调用时,不会隐式传入参数
静态方法,指时表明这个方法属于这个名词空间,函数归结在一起,方便组织管理.
类和对象都可以调用,可以不传参
总结
类除了普通方法都可以调用,普通 方法 需要对象的实例作为第一参数.
实例可以调用所有类中定义的方法(包括类方法,静态方法),普通方法传入实例自身,静态方法和类方法需要找到实例的类.
被@classmethod装饰器装饰的方法是类的绑定方法,参数协程cls,cls是类本身,对象也能调用,参数cls还是还是类本身
被@staticmethod装饰器装饰的方法就是非绑定方法,就是一个普通函数
isinstance和issubclass
isinstance(o,c)
判断o是否为c的实例对象,c可为o的类,或父类及爷爷类
print(isinstance(True,int))
>>>True
issubclass(o,c)
判断o是否为c的子类
print(issubclass(bool,int))
>>>True
反射
反射本质时通过字符串来判断或操作类或者实例的属性
-
hasattr(obj,str)
判断字符串是否是否为类或实例的属性
-
getattr(obj,str,default)
在类或实例中取'字符串'属性,有则返回对应值,无则返回缺省值,若没设定缺省值,抛错
-
setattr(obj,str,value)
设置类或实例中的'字符串'属性,有则更改,无则添加
-
delattr(obj,name)
删除类或实例中的'字符串''属性,有则删除,无则报错
class People:
school = 'DHU'
def __init__(self,name,age):
self.name = name
self.age = age
ag = People('agsol',18)
print(hasattr(ag,'name'))
setattr(People,'major','computer')
print(hasattr(People,'major'))
print(getattr(People,'school'))
delattr(People,'school')
print(hasattr(People,'school'))
>>>True
>>>True
>>>DHU
>>>False
>>>True
单例模式
为了节省内存空间,防止每次(每次实例化的目的以产生相同功能的对象)对类进行实例化都会产生一个新的内存空间
相当于在类的内部加一个中间变量接收这个实例化对象,每次都直接使用实例化对象来调用方法.
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:通过调用__new__的方法
def __new__(cls, *args, **kwargs):
# cls.__new__(cls, *args, **kwargs)
if not cls.__instance:
cls.__instance = object.__new__(cls)
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()
魔术方法
方法名 | 作用 |
---|---|
__init__ |
在调用类时触发.__new__ 没有返回一个空对象时不触发 |
__str__ |
在打印的时候触发,如果没有定义,取调用repr方法, |
__repr__ |
对一个对象获取字符串表达,如果repr没有定义,直接返回object的定义就是显示内存地址信息 |
__del__ |
在对象销毁先执行,不管del方法定义在前或后,总是最后执行 |
__getattr__ |
在对象使用. 调用属性,且此属性没有时触发 |
__setattr__ |
会在对象使用. 调用属性,且属性等于属性值时触发 |
__call__ |
会在对象被调用时触发 |
__new__ |
会在__init__ 执行前触发,new才是第一个执行的函数,用处较少,必须返回一个空对象 |
__getattribute__ |
当发生. 调用属性时,无论属性是否存在都会执行,当getattribute和getattr同时存在,只会执行getattribute,除非getattribute执行过程中抛错 |
__module__ |
表示当前操作的对象在那个模块 |
__class__ |
表示当前操作的对象的类时什么 |
__delattr__ |
当删除属性时触发 |
查看属性
__dir__
:返回类或者对象的所有成员名称列表.dir()函数就是调用__dir__
().如果提供__dir__
(),则返回属性的列表,否则会尽量从__dict__
属性中搜集信息.
dir()对于不同类型的对象具有不同的行为:
如果对象是模块对象,返回的列表包含模块的属性名.
乳如果对象是类型(type)或者类对象(class),返回的列表包含类的属性名,及它的基类的属性名
否则,返回列表包含对象的属性名,它的类的属性名和类的基类的属性名.