目录
-
isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object):pass
obj = Foo()
print(isinstance(obj, Foo))
'''
结果:True
'''
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object):pass
class Bar(Foo):pass
print(issubclass(Bar, Foo))
'''
结果:True
'''
-
反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
# 反射对象中的属性和方法 hasattr getattr setattr delattr
class A():
a = '类的静态变量'
@classmethod
def func(cls):
print('in func')
# hasattr getattr用法
print(getattr(A,'a')) # 反射对象的属性
print(getattr(A,'func')) # 反射类的方法,打印是个内在地址,加上()调用函数
getattr(A,'func')() #输出in func
# hasattr检测是否含有某属性,一般和getattr一起使用
if hasattr(A,'func'): #注意hasattr和getattr参数一样
getattr(A,'func')
#反射模块的属性和方法
"""
程序目录:
my.py
index.py
my.py代码:
day = 'Monday'
def wahaha():
print('wahahaha')
class C:pass
当前文件:
index.py
"""
import my
print(getattr(my,'day')) # 反射模块的属性
getattr(my,'wahaha')() # 反射模块的方法
print(getattr(my,'C')()) # 反射模块的类
#内置模块也能用
import time
print(getattr(time,'time')())
print(getattr(time,'asctime')())
# 要反射的函数有参数怎么办?
print(time.strftime('%Y-%m-%d %H:%M:S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S')) #反射的函数有参数
#反射当前模块成员
import sys
abc = 1
def aa():
print('aaaaa')
print(sys.modules['__main__']) #当前模块
print(getattr(sys.modules['__main__'],'abc')) # 反射自己模块中的变量
getattr(sys.modules['__main__'],'aa')() # 反射自己模块中的函数
# setattr 设置修改变量
class B:
pass
b = B()
setattr(b, 'name', 'bbb')
setattr(B, 'name', 'BBB')
print(B.name)
print(b.name)
# delattr 删除一个变量
delattr(b, 'name')
print(b.name)
delattr(B, 'name')
print(b.name) #报错
-
__str__和__repr__
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
#_*_coding:utf-8_*_
format_dict={
'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type
def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
def __str__(self):
return '(%s,%s)' %(self.name,self.addr)
def __format__(self, format_spec):
# if format_spec
if not format_spec or format_spec not in format_dict:
format_spec='nat'
fmt=format_dict[format_spec]
return fmt.format(obj=self)
s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)
'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
%s和%r
class B:
def __str__(self):
return 'str : class B'
def __repr__(self):
return 'repr : class B'
b=B()
print('%s'%b)
print('%r'%b)
-
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:
def __del__(self):
print('执行我啦')
f1=Foo()
del f1
print('------->')
'''
输出结果:
执行我啦
------->
'''
-
item系列
__getitem__\__setitem__\__delitem__
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
def __getitem__(self, item): #查
if hasattr(self,item):
return self.__dict__[item]
def __setitem__(self, key, value): #改
self.__dict__[key] = value
def __delitem__(self, key): #删
del self.__dict__[key]
#对象通过__getitem__\__setitem__\__delitem__方法来现实像dict(字典)一样通过ke来增删改查
f = Foo('a',18)
print(f['name'])
f['age'] = 20
print(f.__dict__)
f['name'] = 'b'
print(f['name'])
print(f.__dict__)
del f['name']
print(f.__dict__)
'''
结果:
a
{'name': 'a', 'age': 20}
b
{'name': 'b', 'age': 20}
{'age': 20}
'''
-
__new__
构造方法 : 创建一个对象
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs)
a = A()
print(a.x)
'''
结果:
in new function
in init function
1
'''
#单例模式
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
two.a = 3
print(one.a)
# 3
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 41749696
print(id(two))
# 41749696
print(one == two)
# True
print(one is two)
# True
-
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
-
__len__
class Foo:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def __len__(self):
return len(self.__dict__)
F = Foo()
print(len(F))
-
__eq__
class Foo: def __init__(self): self.a = 1 self.b = 2 def __eq__(self, other): if self.__dict__ == other.__dict__: return True else: return False F = Foo() f = Foo() print(F == f) #True print(F.a == f.a) #True print(F.a == f.b) #False
去重面试题
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(p_lst) print(set(p_lst))