python笔记(21)--反射和高阶内置方法
内容目录:
- 反射
- 高阶内置方法
内容回顾:
- 命名空间:类和对象分别存在不同的命名空间中
面向对象的三大特性:继承,多态,封装
- 继承:
- 单继承:(重要程度****)
- 父类(超类,基类)
- 子类(派生类):派生方法和派生属性
- 子类的对象在调用方法和属性:先用自己的,没有才用父类的
- 多继承:(面试会用到)
- 不会超过三个父类,不要超过三层
- 如果子类自己有就用自己的,如果没有就依次从左往后的顺序用父类的
- 抽象类和接口类
- 经典类和新式类:继承规则不同,深度优先和广度优先(面试****)
- super 只能在python3中使用(面试会用到****)
- super是根据mro广度优先顺序找上一个类
- 单继承:(重要程度****)
- 多态:(面试会用到)
- 多态和鸭子类型
- 封装:(面试)
- 私有的
- __名字(双下划线变为私有属性)
- 只能在类的内部调用,子类都无法继承
- 三个装饰器
- @property **** 规范,面试 #@name.stter
- @staticmethod ***
- @classmethod **** 当一个方法只使用了类的静态变量时,就给这个方法加上此装饰器,默认把self改为传cls参数,不能有其他参数
内容详细:
1.isinstance:判断对象和类的关系
#判断结果返回bool类型
class A:pass
class B(A):pass
a = A()
print(isinstance(a,A)) #True isinstance(对象,类)
2.issubclass:判断子类和父类的关系
#判断结果返回bool类型
class A:pass
class B(A):pass
a = A()
print(issubclass(B,A)) #True issubclass(子类,父类)
3.反射
- 是用字符串类型的名字,去操作变量
- 反射对象中的属性和方法:
- hasattr
- getattr
- setattr
- delattr
3.1 getattr(重要)
-
反射对象的属性 ---getattr(对象,属性)
class A: def func(self): print('in func') a = A() a.name = 'liyanan' a.age = 18 # 反射对象的属性 --getattr(对象,属性) ret = getattr(a,'name') # 通过变量名的字符串形式取到的值 print(ret) user = input('>>>>') print(getattr(a,user)) #假如输入name,则执行a.name
-
反射对象的方法 ---getattr(对象,方法)
#接上 # 反射对象的方法 ret = getattr(a,'func') #getattr(a,'func') == a.func ret()
-
反射类的属性
class A: price = 20 def func(self): print('in func') # 反射类的属性 # A.price print(getattr(A,'price'))
-
反射类的方法
class A: price = 20 @classmethod def func(self): print('in func') # 反射类的方法:classmethod staticmethod # A.func() if hasattr(A,'func'): #判断类中是否存在第二个参数的方法 getattr(A,'func')() #如果有就执行
-
反射模块的属性
import my # my为自己写的其他模块 #反射模块的属性 my.day为模块的属性 print(getattr(my,'day'))
-
反射模块的方法
#反射模块的方法 getattr(my,'func')()
-
内置模块也能用反射
-
反射自己模块中的变量和函数
import sys # print(sys.modules['__main__']) year = 2019 def login(): print('welcome') #反射自己模块中的变量 print(getattr(sys.modules[__name__],'year')) user_in = input('>>>') print(getattr(sys.modules[__name__],user_in)) #反射自己模块中的函数 getattr(sys.modules[__name__],'login')()
3.2 hasattr
-
与getattr配合使用,主要做判断
-
注意参数要跟getattr保持一致
import sys year = 2019 if hasattr(sys.modules[__name__],'year'): print(getattr(sys.modules[__name__],'year'))
3.3 setattr(了解)
-
设置修改变量
-
setattr(对象,'要修改的属性','修改的内容')
class A: pass a = A() setattr(a,'name','nezha') setattr(A,'name','taibaijinxing') print(a.name) #打印nezha print(A.name) #打印taibaijinxing
3.4 delattr(了解)
-
删除一个变量
class A: pass a = A() setattr(a,'name','nezha') setattr(A,'name','taibaijinxing') delattr(a,'name') print(a.name) #打印taibaijinxing,因为实例化对象调用了父类的name属性 delattr(A,'name') print(a.name) #报错,没有name属性
4.高阶内置方法
-
__del__
方法:析构函数:在删除一个对象之前,进行的一些收尾工作class A: def __del__(self): #析构函数:在删除一个对象之前进行一些收尾工作 self.f.close() a = A() a.f = open('db.txt','r',encoding='utf-8') # 打开文件,拿到了文件操作句柄 del a #del既执行了这个方法,又删除了变量
-
__call__
方法:实例化后的对象加括号,相当于默认执行了此方法class A: def __init__(self,name): self.name = name def __call__(self, *args, **kwargs): for k in self.__dict__: print(k,self.__dict__[k]) a = A('liyanan')() #实例化对象后加括号相当于执行了内部的__call__方法 #a() 结果为打印self.__dict__中的静态属性 name liyanan
-
item方法
- getitem
- setitem
- delitem
- 附加的delattr
class Foo: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex #getitem方法 def __getitem__(self, item): if hasattr(self,item): #判断item是否存在/传值 return self.__dict__[item] #setitem方法 def __setitem__(self, key, value): self.__dict__[key] = value #delitem方法 def __delitem__(self, key): del self.__dict__[key] #delattr方法 def __delattr__(self, item): print('del obj.key时,我执行') self.__dict__.pop(item) f = Foo('alec','18','男') print(f['name']) #f['']这种格式默认执行了类中的__getitem__方法,等于f.name f['hobby'] = 'python' #默认调用了setitem方法,使类中的字典添加了key和value print(f.hobby,f['hobby']) #结果都为python del f.hobby #先调用类中的delattr方法,如果没有就调用object中的(直接删除) del f['hobby'] #默认调用了delitem方法,删除了类中的静态属性
-
__new__
用法(面试会考)-
所有的类中都是先执行
__new__
方法,再执行__init__
方法 -
使用场景:设计模式:单例模式:只能有一个实例化对象,后面实例化的对象属性都会覆盖第一个对象的属性,如果没有覆盖则用第一个对象的属性
#单例模式 class A: __instance = False #设置一个私有属性 def __init__(self,name,age): self.name = name self.age = age def __new__(cls, *args, **kw): #先执行new,再执行__init__方法 if cls.__instance: return cls.__instance cls.__instance = object.__new__(cls) return cls.__instance yanan = A('yanan',26) yanan.cloth = 'cool' beijing = A('beijing',23) print(yanan) #<__main__.A object at 0x000001B336D38C50> print(beijing) #<__main__.A object at 0x000001B336D38C50> 一样的内存地址,证明只能实例化一个对象 print(yanan.name) #beijing 被第二次实例化对象<北京>给覆盖了 print(beijing.name) #beijing print(beijing.cloth) #cool 第二次实例化对象<北京>没有覆盖,则用第一个对象的属性
-
-
__eq__
方法-
用法:比较实例化后的对象属性是否相等
class A: def __init__(self,name): self.name = name #eq方法 def __eq__(self, other): if self.__dict__ == other.__dict__: return True else: return False ob1 = A('pig') ob2 = A('pig') print(ob1 == ob2) #True
-
-
__hash__
方法-
hash()是系统的哈希用法,以对象的内存地址进行哈希的
-
__hash__
可以自己控制哈希用法class A: def __init__(self,name,sex): self.name = name self.sex = sex def __hash__(self): return hash(self.name+self.sex) a = A('agg','公') b = A('agg','公') print(hash(a)) print(hash(b)) #系统的哈希用法是根据内存地址处理的 #此类中的自己写的哈希算法是根据值来处理的
-
-
示例:
-
实例化对象去重
class A: def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age def __eq__(self, other): if self.name == other.name and self.sex == other.sex: return True return False def __hash__(self): return hash(self.name + self.sex) a = A('agg','公',5) b = A('agg','公',5) print(hash(a)) print(hash(b)) print(set((a,b))) #去重,去除重复的实例化对象(只去重name和sex)
-