内置方法
isinstance 只能判断是否为父子类的关系 不能判断爷爷和孙子的关系(False)
issubclass 判断是否有继承关系 只要有继承关系都为真
class C:
def func(self):pass
class A(C):
def func1(self):print(444)
class B(A):
def func2(self):print(66)
print(issubclass(B,C)) B与C是继承关系
print(isinstance(B,C)) B与C是继承关系不是父类与子类关系
#####
True
Flse
反射
类中反射
对象反射
class A:
b = '666'
def func(self):
print(333)
a = A()
print(getattr(A,'b')) 类反射
c = getattr(a,'func') 对象反射
d = c()
####
666
333
模块反射
import os
getattr(os,'rename')('hehe','fuck')
自己反射
getattr和hasattr
import sys
def login():
print('登陆成功')
def register():
print('注册成功')
func = input('请输入')
if hasattr(sys.modules['__main__'],func):
getattr(sys.modules['__main__'],func)()
增删改对象的属性,和类的属性增删改
setattr delattr
class A:
bb = 'haha'
def __init__(self,name):
self.name = name
def wahaha(self):
print('wahahahahaha')
def qqxing(self):
print('qqqqqxing')
a = A('alex')
setattr(A,'qqxing',qqxing) 为类在增加动态属性
# setattr(a,'qqxing',qqxing) 为对象增加属性
print(A.__dict__)
print(a.__dict__)
a.qqxing()
delattr(A,'bb') 删除类的静态属性
delattr(A,'qqxing') 删除类的动态属性
print(A.__dict__)
a.qqing(a) 为对象增加的方法的调用方式,要传参
__str__ 和 __repr__
这里需要说明的是,其实所有的输出我们能够看得见的都是在输出在文件上的,比如说cmd,pycharm 只不过是特殊的文件形式罢了,所以所有的print的结果都是字符串形式,只是每个不同的数据类型所在的类中的方法又做了不同的处理。我们平时在pycharm中正常的print可以打印出我们想要的东西,只不过是调用了别的类中的__str__的方法。而当我们定义一个类的时候,我们在类中print(对象名) 时,如果类中没有单独定义__str__ 和__repr__的方法,则会调用父类object中的方法,而object中的__str__ 和__repr__就是返回的内存地址。所以由此可见如果我们自己定义这些内置方法就可以输出我们想要的结果
class Teacher:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "Teacher's object %s"%self.name
def __repr__(self):
return 'repr function %s'%self.name
a = Teacher('alex',80)
b = Teacher('egon',80)
print(str(a))
print(repr(a))
print(a)
print(b)
#####
Teacher's object alex
repr function alex
Teacher's object alex
Teacher's object egon
可以看到 当__str__ 和 __repr__同时存在时 print默认去找str方法
class Teacher: def __init__(self,name,age): self.name = name self.age = age # def __str__(self): # return "Teacher's object %s"%self.name def __repr__(self): return 'repr function %s'%self.name a = Teacher('alex',80) b = Teacher('egon',80) print(str(a)) print(repr(a)) print(a) print(b) 当我们把str方法注释掉的时候 print自动去找了repr的方法 而print(str())也去找了repr的方法
class Teacher:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "Teacher's object %s"%self.name
# def __repr__(self):
# return 'repr function %s'%self.name
a = Teacher('alex',80)
b = Teacher('egon',80)
print(str(a))
print(repr(a))
print(a)
print(b)
#####
acher's object alex
<__main__.Teacher object at 0x000002201ED825F8>
Teacher's object alex
Teacher's object egon
把repr的方法注释掉的时候,print都去找了str的方法,而print(repr())的方法直接去找了父类object的repr的方法打印了内存地址
我们的出来结论:
1.当两种方法同时存在时,print默认去找str的方法 2,当str不存在的时候就都可以去找repr 包括print(str()) 3,当repr不在时,正常的print都会找str 而print(repr())则会去找父类的repr 输出内存地址 4,repr是str的备胎 没有了str都可以用repr 都在时又不用他优先用str
__new__
设计模式:单例模式 就是一个类中只有一个实例
class B:
__instance = None #定义一个实例
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
obj = object.__new__(cls) 创建了一个新的空间赋给了__instance 这时候__instance不再是None
cls.__instance = obj
return cls.__instance
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(self.name)
a = B('alex',80)
b = B('egon',20)
print(a)
print(b)
print(a.name)
print(b.name)
####
egon
egon
这段代码中 后面实例化都是在一个内存空间中进行所以 后面每次实例化新对象都是在一个内存空间 新的把旧的覆盖
__item__
增删改
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self,item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
a = Foo('aa')
print(a['name'])
a.age = 18
a['age'] = 22
a.age = 23
del a['age']
print(a.age)
f = Foo('alex')
# f.name = ...
print(f['name']) # f.__getitem__('name')
f['age'] = 18 # 赋值
print(f.age) # 自带的语法
print(f['age']) # 修改
f['age'] = 80
print(f['age']) # 通过实现__getitem__得到的
del f['age']
print(f.age) # 删除