class A:
pass
class B(A):
pass
a = A()
b = B()
- isinstance
- 检测对象与类之间的关系
print(isinstance(a,A))
print(isinstance(b,A))
print(isinstance(a,B))
- issubclass
- 检测类与类之间的关系
print(issubclass(A,B))
print(issubclass(B,A))
反射
好处一:实现可插拔机制,先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
好处二:动态导入模块(基于反射当前模块成员)
- 反射:
使用字符串数据类型的变量名来获取这个变量的值
就是字符串转化成变量名的一个实现
三个场景
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
* input
* 用户输入的如果是a,那么就打印1,如果输入的是b就打印2,如果输入的是name,就打印alex
* 文件
* 从文件中读出的字符串,想转换成变量的名字
* 网络
* 将网络传输的字符串转换成变量的名字
反射类中的变量 : 静态属性,类方法,静态方法
getattr(变量名:命名空间,字符串(必须字符串,不是就会报错):属于一个命名空间内的变量名或者函数名)判断实现
hasattr(变量名:命名空间,字符串:属于一个命名空间内的变量名)反射对象中的变量
反射模块中的变量
import os # os就是一个模块反射本文件中的变量
import sys
print(sys.modules['__main__']) # 本文件的命名空间
print(sys.modules[__name__]) # 反射本文件中的变量 固定的使用这个命名空间
print(sys.modules['__main__'].a)
print(getattr(sys.modules[__name__],'a')) #a是一个变量
obj = getattr(sys.modules[__name__],'Foo')() #反射一个类实例化一个obj
setattr(Foo,'School','OLDOBY') # 接受三个参数 命名空间 ‘变量名’ 变量值
delattr(Foo,'Country') # 接受三个参数 命名空间 ‘变量名’
不是需要程序员定义,本身就存在在类中的方法就是内置方法
内置的方法通常都长这样 : __名字__
名字 : 双下方法、 魔术方法、 内置方法
所有的双下方法,都不需要我们直接去调用,都有另外一种自动触发它的语法
-
__str__, __repr__
__str__
当你打印一个对象的时候 触发str
当你使用%s格式化的时候 触发str
str强转数据类型的时候 触发str__repr__
repr是str的备胎
有__str___的时候执行__str__,没有实现__str__的时候,执行 __repr__
repr(obj)内置函数对应的结果是 __repr__的返回值
当你使用(%r)格式化的时候 触发repr
class Foo:
def __str__(self): #2
return 'Foo.str'
def __repr__(self): #4
return 'Foo.repr'
class Son(Foo):
# pass
def __str__(self): #1
return 'Son.str'
def __repr__(self):
return 'Son.repr' #3
s1 = Son()
print(s1)
反射总结:
反射 用字符串类型的变量名来获取变量的值
hasattr(命名空间,'变量名')
getattr(命名空间,'变量名')
类名.静态属性 getattr(类名,'静态属性')
类名.类方法() getattr(类名,'类方法')()
类名.静态方法() getattr(类名,'静态方法')()
对象.对象属性 getattr(对象,'对象属性')
对象.方法() getattr(对象,'方法')()
模块名.方法名
模块名.类名
模块名.变量
模块名.函数
本文件反射
import sys
getattr(sys.modules[__name__],'所有定义在这个文件中的名字')
setattr 给命名空间的某一个名字设置一个值
delattr 删除某一个命名空间中变量对应的值
内置方法
不用调用调用这个方法就可以出发这个方法的执行
class Foo:
def __str__(self):
return 'abcd'
def __repr__(self):
return 'dcba'
obj = Foo()
__str__ :
print(obj)
'%s'%obj
str(obj)
__repr__ : # 当使用会触发str方法的方式,但是Foo类内部又没有实现__str__方法的时候,都会调用__repr__
'%r'%obj
repr(obj)
- __new__
在init之前,实例化对象的第一步是new创建了一个空间
class Foo:
def __init__(self): # 初始化方法
print('执行了init')
def __new__(cls, *args, **kwargs): # 构造方法
# object.__new__(cls)
print('执行了new')
return object.__new__(cls)
obj = Foo()
new 是小人捏出来了
init 给小人穿衣服
设计模式 常用的23种
java里来的
python
推崇设计模式 java开发
贬低设计模式 纯python开发
单例模式
一个类 只有一个实例的时候 单例模式
class Foo:
__instance = None
def __init__(self,name,age): # 初始化方法
self.name = name
self.age = age
self.lst = [name]
def __new__(cls, *args, **kwargs): # 构造方法
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance
obj1 = Foo('alex',20)
obj2 = Foo('egon',22)
print(obj1.lst,obj2.lst)
- __del__:析构方法 : 在删除这个类创建的对象的时候会先触发这个方法,再删除对象
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
self.file = open('file',mode = 'w')
def write(self):
self.file.write('sjahgkldhgl')
def __del__(self): # 析构方法 : 在删除这个类创建的对象的时候会先触发这个方法,再删除对象
# 做一些清理工作,比如说关闭文件,关闭网络的链接,数据库的链接
self.file.close()
print('执行del了')
f = Foo('alex',20)
print(f)
- __len__
class Foo:
def __len__(self):
return 1
obj = Foo()
print(len(obj))
- __eq__
print(alex == alex2) # alex.eq(alex2)
- __hash__
1.每次执行hash值都会变化
2.在一次执行的过程中对同一个值得hash结果总是不变的
字典为什么寻址快
dic = {'name':'alex','age':83,'sex':'不详'}
字典在内存中是如何存储的?
为什么字典的key必须可hash
hash算法
1.对于相同的值在一次程序的运行中是不会变化的
2.对于不同的值在一次程序的运行中总是不同的