Day27 of learning python--反射和部分双下方法
一、面向对象的复习
命名空间:类和对象分别存在不同的命名空间中,对象能找到类的,类找不到对象的。
继承:super 只能在python3中使用,super是根据mro广度优先顺序找上一个类的。
封装:私有的,只能在类的内部调用,子类都无法继承
多态:鸭子类型
3个装饰器:
@property 伪装成一个静态属性,会使用@name.setter
@staticmethod 在面向对象程序中,如果一个函数,既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数变成一个静态方法。类方法和静态方法都是类调用,对象也同样可以调用类方法和静态方法,静态方法没有默认参数。
@classmethod 当一个方法只使用了类的静态变量时,就给这个方法加上@classmethod装饰器,默认传cls参数,就是修改类的静态属性,在调用修改这个属性时,就是整个改变这个属性值
1 class Goods: 2 __discount = 0.8 3 @classmethod 4 def change_discount(cls): 5 cls.__discount =0.5 6 7 Good.change_discount()
组合:
class Course: def __init__(self,name,price,period): self.name = name self.price = price self.period = period class Classes: def __init__(self,name): self.name = name self.course = python.name # 在第一次定义的时候,就已经是写死了,后面python的改变,而不会影响到此改变的 python = Course('python',19800,'6 months') pys9 = Classes('python_s9') print(pys9.course) # print(pys9.course.name) python.name = 'python全栈' print(pys9.course) # print(pys9.course.name)
二、isinstance 和 issubclass
isinstance(obj,cls)检查obj是否是cls的对象
1 class A:pass 2 a = A() 3 print(isinstance(a,A))
issubclass(sub,super)检查sub类是否是super类的派生类
class A:pass class B(A):pass print(issubclass(B,A))
三、反射
python面向对象中的反射:通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)
getattr的使用
1.反射类对象中的属性&方法
class A: def func(self): print('in func') a = A() a.name = 'alex' a.age = 84 #反射对象的属性 ret = getattr(a,'name') # 通过变量名的字符串形式取值 print(ret) # 变量名= input('>>>') # print(getattr(a,变量名)) # print(a.__dict__[变量名]) # 反射方法 # a.func() ret = getattr(a,'func') #绑定一个方法的地址 ret()
2.反射类的属性&方法
class A: price = 20 @classmethod def func(self): print('in func') # 反射类的属性 # A.price print(getattr(A,'price')) # 反射类的方法:classmethod staticmethod # A.func([]) A.func() if hasattr(A,'func'): ret = getattr(A,'func')()
3.反射模块的属性&方法
#my.py day = 'Monday' # 周一 def wahaha(): print('wahaha') import my # 反射模块的属性 # print(my.day) print(getattr(my,'day')) #反射模块的函数 getattr(my,'wahaha')()
4.反射模块中类
#my.py class C: pass import my print(getattr(my,'C')()) # 加括号就是实例化一个对象
5.反射内置模块中的方法
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')) 结果: 1542188398.019721 Wed Nov 14 17:39:58 2018 2018-11-14 17:39:58 2018-11-14 17:39:58
6.反射自己模块中的变量&方法
def qqxing(): print('qqxing') year = 2018 import sys #print(sys.modules['__main__'].year) #反射自己模块中的变量 # print(getattr(sys.modules['__main__'],'year')) # 反射自己模块中方法 # getattr(sys.modules['__main__'],'qqxing')() 变量名 = input('>>>') print(getattr(sys.modules[__name__],变量名))
注意:由于这个模块可能被其他模块调用,所有要把‘__main__'写成__name__,这样就不会写死了,否则在其他模块中,不能调用自己的模块的变量和方法
setattr的使用
用来修改变量
class A: pass a = A() setattr(A,'name','alex') setattr(a,'name','naza') print(A.name) print(a.name) 结果: alex naza
delattr的使用
删除变量
class A: pass a = A() setattr(A,'name','alex') setattr(a,'name','naza') delattr(a,'name') print(a.name) #对象找不到,找类中的 delattr(A,'name') # print(A.name) 结果: alex
hasattr的使用
判断是否有这个变量,一般和getaattr搭配着使用
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #检测是否含有某属性 print(hasattr(obj,'name')) print(hasattr(obj,'say_hi'))
四、类的双下方法
print(1,'1') print(repr(1)) print(repr('1')) 结果: 1 1 1 '1'
__str__的使用
class A: def __str__(self): return "A's object" def func(self): return 'wahaha' a = A() print(a) # 打印一个对象的时候,就是调用a.__str__ #a.__str__ -- > object 结果: A's object
注意:对象的基类是object ,这里面有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
# l = [1,2,3,4,5] #实例化,实例化了一个列表类的对象 #print(l) # 此处重定制了
print('%s:%s'%('A',a)) # %s str() 直接打印,实际上都是走的__str__
print(obj)/'%s'%obj/str(obj)的时候,实际上内部调用了obj.__str__方法,如果str方法有,那么他就返回的必定是一个字符串
__repr__的使用
class A: def __repr__(self): return "A's object" def func(self): return 'wahaha' a = A() print(repr(a)) print('%s:%r'%('a',a) 结果: A's object a:A's object
注意:%r repr() 实际走的都是__repr__,repr 是str的备胎,如果使用str()时没有找到__str__()的这个方法,则会去找__repr__()。
__del__的使用
class A: def __del__(self): self.f.close() #所以在此处删除时,则做一些收尾工作,把文件关闭 print('执行我啦!') a = A() a.f = open() # 打开文件,第一在操作系统中打开了一个文件,拿到了文件操作符在内存中 del a # a.f 拿到的文件操作符消失在了内存中,但是没有把文件关闭 import time time.sleep(3) # del a # del 即执行了这个方法,有删除了这个这个对象 # print(a) #引用计数,自动计算,为O时删除变量
__call__的使用
class A: def __init__(self,name): self.name = name def __call__(self): ''' 打印这个对象中的所有属性 :return: ''' for k in self.__dict__: print(k,self.__dict__[k]) a = A('alex') a() #相当于a = A('alex')(),直接使用对象加括号,调用__call__方法
浙公网安备 33010602011771号