isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def hasattr(*args, **kwargs): # real signature unknown """ Return whether the object has an attribute with the given name. This is done by calling getattr(obj, name) and catching AttributeError. """ pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def getattr(object, name, default=None): # known special case of getattr """ getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y. When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case. """ pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def setattr(x, y, v): # real signature unknown; restored from __doc__ """ Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v'' """ pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def delattr(x, y): # real signature unknown; restored from __doc__ """ Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y'' """ pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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')) #获取属性 n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','不存在啊')) #报错 #设置属性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #删除属性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,则报错 print(obj.__dict__)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo(object): staticField = "old boy" def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' @staticmethod def bar(): return 'bar' print getattr(Foo, 'staticField') print getattr(Foo, 'func') print getattr(Foo, 'bar')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # -*- coding:utf-8 -*- import sys def s1(): print 's1' def s2(): print 's2' this_module = sys.modules[__name__] hasattr(this_module, 's1') getattr(this_module, 's2')
__str__和__repr__
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#_*_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'))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def __del__(self): print('执行我啦') f1=Foo() del f1 print('------->') #输出结果 执行我啦 ------->
item系列
__getitem__\__setitem__\__delitem__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def __init__(self,name): self.name=name def __getitem__(self, item): print(self.__dict__[item]) def __setitem__(self, key, value): 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') f1['age']=18 f1['age1']=19 del f1.age1 del f1['age'] f1['name']='alex' print(f1.__dict__)
__new__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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)) # 29097904 print(id(two)) # 29097904 print(one == two) # True print(one is two) 单例模式
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
__len__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a))
__hash__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self): self.a = 1 self.b = 2 def __hash__(self): return hash(str(self.a)+str(self.b)) a = A() print(hash(a))
__eq__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self): self.a = 1 self.b = 2 def __eq__(self,obj): if self.a == obj.a and self.b == obj.b: return True a = A() b = A() print(a == b)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5])
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# class A: # pass # class B(A): # pass # 多继承 # class File: # def open(self): # pass # def close(self): # pass # class DB: # def connect(self): # pass # def disconnect(self): # pass # class C(File,DB): # pass # 多继承: # 假设一个类,既拥有A类的功能,又拥有B类的功能,就会用到多继承。 # 多继承之后,写在父类位置上的类都被称为我子类的父类了。 # class A: # def func(self): # print('A') # class B: # def func(self): # print('B') # class C(A,B): # pass # c = C() # c.func() # PY2.7 / PY3.X 新式类和经典类 - 多继承 # 多继承在新式类中的继承规则 # 在经典类中的继承规则 class A: def func(self): print('A') class B(A): pass # def func(self): # print('B') class C(A): pass # def func(self): # print('C') class D(B,C): pass # def func(self): # print('D') # d = D() # d.func() class A: def func(self): print('A') class B(A): pass # def func(self): # print('B') class C(A): pass def func(self): print('C') class D(B): pass # def func(self): # print('D') class E(C): pass def func(self): print('E') class F(D,E): pass # def func(self): # print('F') print(F.mro()) # 类的多继承 # python3.x # 所有的类都是新式类 # 所有的新式类都默认继承object类 # object类是所有python3中类的父类/基类 # 这个类中提供了很多基础的方法 # 使得即使我们创建一个类什么也不做,仍然可以使得这个类具备python中类的一些基本功能 # 多继承 # 所有的新式类在多继承寻找名字的过程中都遵循广度优先 # 横向是广度,纵向是深度 # 广度优先 :所谓的广度优先并不是一味的横向运动, # 而是在找寻下一个点的时候,要思考这个点在后面的其他点还有没有直接找到他的可能性 # 如果有,那么我们现在要先放弃这个点,先横向寻找 # 如果后面已经没有办法走到这个点了,那应该纵向先寻找之后再往横向走 # mro方法: # 在新式类中给我们提供了一个mro方法,让我们能够查看多个类之间的继承顺序 # 在多继承中的super # super遵循的永远是mro顺序 # class A: # def func(self): # print('A') # class B(A): # def func(self): # super().func() # print('B') # class C(A): # def func(self): # super().func() # print('C') # class D(B,C): # def func(self): # super().func() # print('D') # # d = D() # d.func() # python2.7 # 继承object : # 经典类 # class A:pass # 新式类并存 # class A(object):pass # 多继承 # 新式类的继承特点仍然是广度优先 # 经典类的继承特点 就是 深度优先 # 在寻找类中的方法的时候,总是从最左边的一条分支开始,一直走到底,再依次向右走 # 经典类是没有mro方法的 # super(子类名,子类对象).方法名() # 在py2.7中使用super是必须要传递子类名和子类对象这两个参数的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Pay:pass class Ali(Pay): def pay(self,name,money): # 调用支付宝提供给我的一个方法 # 链接支付宝 # 调用付款方法 # 得到返回值 # 显示支付是否成功 pass class Wechat(Pay): def pay(self,name,money): # 调用支付宝提供给我的一个方法 # 链接支付宝 # 调用付款方法 # 得到返回值 # 显示支付是否成功 pass ali_obj = Wechat() # java # def pay(str name,Pay payobj,int money): # payobj.pay(name,money) # python def pay(name,payobj,money): payobj.pay(name,money) # pay('alex',ali_obj,100) # python是没有多态 # python当中处处是多态 # 多态 : 利用面向对象的继承 实现的一种传参的兼容方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# class Goods: # discount = 0.7 # __discount = 0.8 # 对外不可用了 # # def __init__(self): # # pass # def func(self): # pass # __双下方法__ __魔术方法__ # __变量名 私有的,私有的都不能在类的外部直接访问 # 是因为在类的内部对于__名字的值有一个特殊的变形 _类名__名字 # print(Goods.discount) # print(Goods.__discount) # print(Goods._Goods__discount) # class Goods: # def __init__(self,o_price): # self.__price = o_price # def get_price(self): # return self.__price # apple = Goods(5) # print(apple.get_price()) # 私有的对象属性 # 私有的静态属性 # 定义私有 : # 是为了保护变量不被随意修改,为了某个方法只在类的内部被调用 # 私有的方法和属性不能被子类继承 # 在类中调用的所有的私有名字都是直接找本类中的私有名字 # 定义私有的方法 # class Login: # def __init__(self,name,pwd): # self.name = name # self.pwd = self.__get_pwd(pwd) # 12345 # # def __get_pwd(self,pwd): # # 一系列算法 # return pwd # 继承 : class Foo: def __init__(self): self.__func() # _Foo__func def __func(self): # _Foo__func print('in Foo') class Son(Foo): pass # def __func(self): # print('in Son') def myfunc(self): self.__func() # _Son__func() obj = Son() obj.myfunc() # 私有 # 私有的静态属性 # 私有的对象属性 # 私有的方法 # 定义私有 : # 变量 # 是为了保护变量不被随意修改 # 方法 # 为了某个方法只在类的内部被调用 # 私有的方法和属性不能被子类继承 # 在类中调用的所有的私有名字都是直接找本类中的私有名字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 单继承 # 多继承 3个类 # 封装 __名字 变形机制/基础用法 # 68个内置函数 # 55个 # @property # @classmethod # @staticmethod # from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # 用来装饰一个方法,将这个方法伪装成一个属性 # def area(self): # return pi * self.r**2 # @property # def perimeter(self): # return 2* pi * self.r # # c1 = Circle(10) # # 圆形对象 计算面积 动词 # # 的面积 名词 - 属性 # print(c1.r) # print(c1.area) #---> c1.area() # print(c1.perimeter) #---> c1.perimeter() # class Goods: # def __init__(self,price): # self.__price = price # # def get_price(self): # return self.__price # @property # def price(self): # return self.__price # # apple = Goods(5) # apple.get_price() # apple.price # property 用来装饰一个方法,将这个方法伪装成一个属性 # 有一些方法,它本身的返回值应该作为这个对象的属性 # 当我们想给一个私有的变量设置一个查看方法的时候 # property只是从逻辑的合理性和程序的美观度上面做出了一些修正 # class Goods: # __discount = 0.8 # def __init__(self,price): # self.__price = price # # @property # def price(self): # return self.__price * Goods.__discount # # @classmethod # def change_discount(cls,new): # 当前类 Goods # cls.__discount = new # 不需要使用对象调用 # 在传参数的时候不需要传类名 # Goods.change_discount(0.7) # apple = Goods(5) # banana = Goods(10) # print(banana.price) # print(apple.price) # Goods.change_discount(0.9) # print(banana.price) # print(apple.price) # 当我们写了一个类中的方法,发现并没有使用到对象的任何属性 # 只是用到了类的命名空间中的变量(除了接收self参数的方法) # 你就将这个方法定义成一个被@classmethod装饰器装饰的方法 # 这个方法就被称为一个类方法 # @staticmethod # 面向对象编程 没有函数的概念 # class Beginer: # @staticmethod # def login(): # 本质上就是一个函数,也不需要默认的类,self对象 # pass # # Beginer.login() # @property 把一个普通的方法装饰成属性 # @classmethod 把一个普通的方法装饰成类方法, # 调用方式 类名.方法名 # 定义方式 参数 从 self --> cls # @staticmethod 把一个普通的方法装饰成类中的函数/静态方法 # 调用方式 类名.方法名 # 定义方式 参数 从self --> 没有默认必须传的参数了 # class A:pass # class B(A):pass # b = B() # # print(isinstance(对象,类)) # print(isinstance(b,B)) # print(isinstance(b,A)) # # print(type(b) is B) # print(type(b) is A) # print(issubclass(子类,父类)) # print(issubclass(B,A)) # print(issubclass(A,B))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# name = 'alex' # age = 123 # inp = input('>>>') # 'age' / 'name' # 有些时候,我们需要通过字符串数据类型的变量名来获取变量的值 # 几个作用域需要考虑 # 类中的 getattr(类名,‘变量名’) # 对象中的 getattr('对象名','变量名') # 本文件中的 getattr(sys.modules[__name__],'变量名') # 模块中的 getattr('模块名','变量名') # class A: # Country1 = 'China' # Country2 = 'America' # @classmethod # def show_country(cls): # print(cls.Country1) # print(cls.Country2) # print(A.Country) # ret = getattr(A,'Country1') # # print(ret) # print(hasattr(A,'Country1')) # print(hasattr(A,'Co')) # inp = input('>>>') # if hasattr(A,inp): # print(getattr(A,inp)) # print(A.show_country) # ret = getattr(A,'show_country') # ret() # class Student: # def __init__(self,name): # self.name = name # def show_courses(self): # print('查看可选择的课程') # xiaoming = Student('小明') # print(xiaoming.name) # print(getattr(xiaoming,'name')) # xiaoming.show_courses() # getattr(xiaoming,'show_courses')() import sys # name = 'alex' # age = 123 # print(name) # print(sys.modules[__name__].name) # print(getattr(sys.modules[__name__],'name')) # def login(): # print('login') # # def register(): # print('register') # inp = input('>>>') # getattr(sys.modules[__name__],inp)() # 反射本模块中的类 # class Student: # pass # # class Mangaer: # pass # # cls = input('>>>') # clas = getattr(sys.modules[__name__],cls) # print(clas()) # import time # # time.time() # # time.localtime() # print(getattr(time,'time')()) # print(getattr(time,'localtime')()) # setattr delattr # class A: # abc = 'aabbcc' # setattr(A,'abc','ccbbaa') # print(A.abc) # delattr(A,'abc')# del A.abc # print(A.abc)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 学院选课系统 import sys class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher class Student: operate_lst = [('查看可选课程','show_courese'), ('选择课程','choose_course'), ('查看已选课程','show_selected_course'), ('退出','exit')] def __init__(self,name): self.name = name self.courses = [] def show_courese(self): print('查看可选课程') def choose_course(self): print('选择课程') def show_selected_course(self): print('查看已选课程') def exit(self): print('退出') class Manager: operate_lst = [('创建课程', 'create_course'), ('创建学生', 'create_student'), ('查看可选课程', 'show_courese'), ('查看学生', 'show_students'), ('查看所有学生以及所选课程', 'show_stu_course'), ('退出', 'exit')] def __init__(self,name): self.name = name def create_course(self): # pickle 内置方法的用法 print('创建课程') def show_courese(self): print('查看可选课程') def create_student(self): print('创建学生') def show_students(self): print('查看所有学生') def show_stu_course(self): print('查看所有学生以及所选课程') def exit(self): print('退出') # 从管理员功能开始开发 # 登录 # 自动根据你的用户名和密码 判断身份 def login(): usr = input('username :') pwd = input('password :') with open('userinfo') as f: for line in f: user,passwd,identify = line.strip().split('|') if usr == user and passwd == pwd: print('登录成功') return {'usr':usr,'identify':identify} else: print('登录失败') return {'usr': usr, 'identify': None} ret = login() if ret['identify']: cls = getattr(sys.modules[__name__],ret['identify']) obj = cls(ret['usr']) for index,i in enumerate(cls.operate_lst,1): print(index,i[0]) ind = int(input('num >>')) operate = cls.operate_lst[ind-1][1] getattr(obj,operate)()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 什么是模块? # 一组功能的集合 # import my_module # 只要是py文件都可以称为模块 # 模块的名字 必须符合变量的命名规范 # 导入一个模块相当于执行了这个py文件 # print(my_module.name) # my_module.read1() # 模块重命名 # import my_module as m # print(m.name) # m.read1() # import sys as s # print(s.path) # 导入多个模块 # import os,sys # import os as o,sys as s # 三种模块 # 内置模块 # 第三方模块 # 自定义模块 # from import # from my_module import name as n,read1 as r # print(n) # r() # 模块重命名 # 导入多个名字 # * # from my_module import * # print(name) # read1() # 模块搜索路径, # 一个模块能不能被导入 就看这个模块所在的目录是否在sys.path中 # import my_module # import sys # print(sys.path) # 如果被执行的文件和要导入的文件在同级目录下,可以直接导入 # 如果被执行的文件和要导入的文件不在同级目录下 # 需要我们自己修改sys.path # import sys # sys.path.append(r'D:myprojectpy23day7glanceapi') # import policy # policy.get() # if __name__ == '__main__': import my_module # __name__是一个变量 # 当__name__所在的文件被直接执行的时候,那么__name__ == '__main__' # 当__name__所在的文件被导入的时候,那么__name__ ==‘模块的名字’ # if __name__ == '__main__': # print('是你希望在被直接执行的时候才会走的逻辑') # import calculator # ret = calculator.cal('1-2+3') # print(ret) # 包 # import sys # print(sys.path) # import # import glance.api.policy as policy # policy.get() # from import # from glance.api import policy # policy.get() # from glance.api.policy import get # get()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def cal(s): eval(s) if __name__ == '__main__': inp = input('>>>') print(cal(inp))