python面向对象反射及内置方法
一.isinstance与issubclass
isinstance:可以判断x是否是y类的实例化对象
issubclass:判断B类是否A类的子类
d={'a':1}
print(isinstance(d,dict))
class A:
pass
class B(A):
pass
print(issubclass(B,A))
二.反射
- hasattr(obj, str) 判断obj中是否包含str成员
- getattr(obj,str) 从obj中获取str成员。
- setattr(obj, str, value) 把obj中的str成员设置成value。这⾥的value可以是值,也可以是函数或者⽅法。
- delattr(obj, str) 把obj中的str成员删除掉。
class People:
country = 'China'
def __init__(self, name):
self.name = name
def eat(self):
print("%s is eating" % self.name)
return '你拿到我了'
peo1 = People('tom')
#操作函数属性
#1.判断有没有
print(hasattr(People,'eat'))
#2.查取出来
print(getattr(People,'eat')(peo1))
#3.增
def func():
return 'hello'
setattr(People,'speak',func())
print(People.__dict__)
#4.删除
print(People.__dict__)
delattr(People,'eat')
print(People.__dict__)
#操作数据属性
print(hasattr(peo1, 'name')) # peo1.name
print(hasattr(peo1, 'eat')) # peo1.eat
print(getattr(peo1,'xxx',None))#找不到属性就返回None
res=getattr(peo1,'name')
print(res)
setattr(peo1,'age',18)
print(peo1.age)
delattr(peo1,'name')
三. 内置方法
__str__
:在对象被打印时自动触发,可以用来定义对象被打印时的输出信息,必须返回一个字符串的值.
应该在方法内采集对象的相关的信息,然后根据需要拼成字符串的格式返回
__del__
(析构方法):在对象被删除之前自动触发,可以用来做回收系统资源相关的事情.
__str__
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '<name:%s age:%s>'%(self.name,self.age)
obj=People('tom',18)
print(obj)
__del__
class People:
def __init__(self, name, age):
self.name = name
self.age = age
self.f=open('a.txt','r',encoding='utf-8')
def __del__(self):
# print('run..........')
# 做回收系统资源相关的事情
self.f.close()
obj = People('tom', 18)
# print(obj)
# del obj
print('主')
__format__
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
__format_dict = {
'n-a': '名字是:{obj.name}-年龄是:{obj.age}', # 名字是:tom-年龄是:18
'n:a': '名字是:{obj.name}:年龄是:{obj.age}', # 名字是:tom:年龄是:18
'n/a': '名字是:{obj.name}/年龄是:{obj.age}', # 名字是:tom/年龄是:18
}
def __format__(self, format_spec):
if not format_spec or format_spec not in self.__format_dict:
format_spec = 'n-a'
fmt = self.__format_dict[format_spec]
print(fmt) #{obj.name}:{obj.age}
return fmt.format(obj=self)
s1 = Student('tom', 24)
ret = format(s1, 'n/a')
print(ret) # tom/24
__item__
class Foo:
def __init__(self, name):
self.name = name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
print('obj[key]=tom赋值时,执行我')
self.__dict__[key] = value
def __delitem__(self, key):
print('del obj[key]时,执行我')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,执行我')
self.__dict__.pop(item)
f1 = Foo('sb')
print(f1.__dict__)
f1['age'] = 18
f1.hobby = '泡妞'
del f1.hobby
del f1['age']
f1['name'] = 'tom'
print(f1.__dict__)
__new__
其实__init__
是在类实例被创建之后调用的,它完成的是类实例的初始化操作,而__new__
方法正是创建这个类实例的方法
class Person:
def __new__(cls, *args, **kwargs):
print('调用__new__,创建类实例')
return super().__new__(Person)
def __init__(self, name, age):
print('调用__init__,初始化实例')
self.name = name
self.age = age
def __str__(self):
return '<Person: {}({})>'.format(self.name, self.age)
p1 = Person('张三', 24)
print(p1)
调用__new__,创建类实例
调用__init__,初始化实例
<Person: 张三(24)>
__new__
方法在类定义中不是必须写的,如果没定义的话默认会调用object.__new__
去创建一个对象(因为创建类的时候默认继承的就是object)。
如果我们在类中定义了__new__
方法,就是重写了默认的__new__
方法,我们可以借此自定义创建对象的行为。
举个例子:
重写类的__new__
方法来实现单例模式。
class Singleton:
# 重写__new__方法,实现每一次实例化的时候,返回同一个instance对象
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = super().__new__(Singleton)
return cls._instance
def __init__(self, name, age):
self.name = name
self.age = age
s1 = Singleton('张三', 24)
s2 = Singleton('李四', 20)
print(s1, s2) # 这两实例都一样
print(s1.name, s2.name)
__call__
__call__
方法的执行是由对象后加括号触发的,即:对象()。拥有此方法的对象可以像函数一样被调用。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __call__(self, *args, **kwargs):
print('调用对象的__call__方法')
a = Person('张三', 24) # 类Person可调用
a() # 对象a可以调用
__new__
,__init__
,__call__
等方法都不是必须写的。