1.多态
#多态 多态是指对象如何通过他们共同的属性和动作来操作及访问,而不需要考虑他们具体的类 运行时候,多种实现 反应运行时候状态 class H2O: def __init__(self,name,temperature): self.name = name self.temperature = temperature def turn_ice(self): if self.temperature < 0: print("[%s]温度太低结冰了" %self.name) elif self.temperature > 0 and self.temperature < 100: print("[%s]液化成水" %self.name) elif self.temperature > 100: print("[%s]温度太高变成了水蒸气" %self.name) def aaaaaaa(self): pass class Water(H2O): pass class Ice(H2O): pass class Steam(H2O): pass w1=Water("水",25) i1=Ice("冰",-20) s1=Steam("蒸汽",3000) w1.turn_ice() i1.turn_ice() s1.turn_ice() #以下作法,同上 def func(obj): obj.turn_ice() func(w1) func(i1) func(s1)
类的继承有两层含义:1.改变 2.扩展
多态就是类的这两层意义的一个具体的实现机制,即,调用不同的类实例化得对象下的相同方法,实现的过程不一样。python中的标准类型就是多态概念的一个很好的示范。
2.封装prt1
class People: __star = "earth" __star1 = "earth123" __star2 = "earth456" __star3 = "earth789" def __init__(self,id,name,age,salary): print("---->",self.__star) self.id = id self.name = name self.age = age self.salary = salary def get_id(self): print("我是私有方法啊,我找到的ID是[%s]" %self.id) #访问函数 def get_star(self): print(self.__star) # print(People.__dict__) p1 = People("123456789","alex","18",100000) # print(p1.__star) # print(People.__dict__) # print(p1.__star) print(p1._People__star) #方法1访问__star="earth" p1.get_star() #方法2访问__star="earth"
将上述代码文件导入test模块。
from package import People #先运行package中代码,接着运行test中代码 p1 = People("123123123123","alex","18",100) #调用People类 p1.get_id() #调用get_id()函数
3.反射
反射使程序在运行时,动态修改自己结构和行为的能力
反射作用具体化:A在写程序,要用到B的类,B不在上班,A调用反射机制继续写代码,等到B完成后,再实现B部分类的功能
getattr()动态获取属性值
setattr()设置属性值
hasattr()用于判断对象是否具有属性值
class BlackMedium: feture = "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(b1.__dict__) #getattr和setattr用于获取和设置 # hasattr() 用于判断object对象中是否存在name属性值,属性包含变量和方法,有则返回True,没有则返回False print(hasattr(b1,"name")) print(hasattr(b1,"sell_house")) print(getattr(b1,"name")) print(getattr(b1,"rent_house")) func=getattr(b1,"rent_house") func() print(getattr(b1,"111","234")) #如果不存在对象“111”,输出默认值“234” # b1.sb = True setattr(b1,"sb",True) setattr(b1,"sb1",123) setattr(b1,"name","SB") #修改name的value print(b1.__dict__) del b1.sb #删除对象的第一种操作 # del b1.sb1 # delattr(b1,"sb") #删除对象的第二种 print(b1.__dict__)
例子:
列出ftp_client和yuyukun_client的py文件;
运行程序;
图1 B中处理的工作
图2 A中运行程序的结果
图3 A中运行程序的结果(get到B中的put对象)
实例作为参数传入匿名函数中,实例同时也可调用自己
#实例作为参数传入,可以调用 class BlackMedium: feture = "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("万成置地","天露网") setattr(b1,"func",lambda x:x+1) setattr(b1,"func1",lambda self:self.name+"sb") print(b1.__dict__) print(b1.func(5)) print(b1.func1(b1))
4.动态模块导入_顶级模块名和当前模块名区别
顶级模块可调用函数中内容
当前模块不能调用函数中内容
图4 顶级模块名和当前模块名区别
当外部模块有下划线时,导入注意点以及如何导入外部所有模块
动态导入底层基于反射
# module_t.t.test1() from m1.t import * #用*导入m1/t中所有文件,不能调用 test1() _test2() #模块函数中加入“_”,不能在其他文件中调用,可以用下划线方式调用导入 from m1.t import test1,_test2 test1() _test2()
6.类内置attr属性:根据自己状态来检验
6.1类中4个内置函数
hasattr(),hasattr(obj,"name") --> 判断“name”是否存在,返回True or False
getattr(), getattr(obj,"name",default = "xxx") --> 获取“name” 值,不存在返回xxx getattr()找不到对象出发
setattr(),setattr(obj,"name","alex") --> obj.name="alex" setattr()设置属性时出发
delattr(),delattr("obj","name") --> del obj.name delattr()删除属性时出发
实例调用对象触发4个类内置属性,该方法与类本身无关,与实例‘.’该调用方法有关。
class Foo: x = 1 def __init__(self,y): self.y = y def __getattr__(self, item): print("执行__getattr__") def __delattr__(self, item): print("删除操作__delattr__") def __setattr__(self, key, value): print("__setattr__执行") self.__dict__[key] = value f1 = Foo(10) print(f1.y) print(getattr(f1,"y")) f1.ssss del f1.y #删除触发__delattr__ del f1.x f1 = Foo(10) print(f1.__dict__) f1.z = 2 print(f1.__dict__)
代码运行结果: __setattr__执行 10 10 执行__getattr__ 删除操作__delattr__ 删除操作__delattr__ __setattr__执行 {'y': 10} __setattr__执行 {'y': 10, 'z': 2}
上述代码解释:其中delattr(),setattr()操作触发对应函数功能,调用getattr()不触发对应函数功能,只有在get不到类中的对象时,才会触发getattr()函数
6.2 类中其它函数
isinstance(obj,cls)
#判断对象名是否和类一致
class Foo: pass f1 = Foo() print(isinstance(f1(f1是对象名),Foo(Foo是类)))
issubclass(sub,super)
#判断类1是否是类2的子类/继承类 class Foo: pass f1 = Foo() print(isinstance(f1,Foo)) class Bar(Foo): pass print(issubclass(Bar(类1),Foo(类2)))
6.3 __getattr__, __getattribute__
class Foo: def __init__(self,x): self.x = x def __getattr__(self, item): print("执行的是getattr") # return self.__dict__[item] def __getattribute__(self,item): print("执行的是getattribute") # print("执行的是getattribute") # raise AttributeError("抛出异常了") raise TabError("xxxxx") f1 = Foo(10) # f1.x f1.xxxxxx123 #找不到对象,执行getattr()语句 #或者找到对象,输出类中正常数值 #getattr与getattribute区别 #__getattr__触发时机,通过__getattribute__中的raise AttributeError来识别异常,并返回给getattr #TabError触发,进入中止程序
7.二次加工:继承与派生。用于定制自己的数据类型,查看类型
#二次加工标准类型(包装用于定制自己的数据类型) class List(list): def append(self, p_object): #l1=self,p_object=11111 if type(p_object) is str: # list.append(self,p_object) super().append(p_object) else: print("只能添加字符串类型") def show_middle(self): mid_index = int(len(self)/2) return self[mid_index] l1 = List("hello_world") l1.append(12345) l1.append("SB") #自动触发 def append(self, p_object) print(l1) l2 = list("hello_world") print(l2,type(l2)) print(l1,type(l1)) print(l1.show_middle())
8.组合方式完成授权(权限管理),防止对象权限滥用
包装=继承+派生
import time class FileHandle: def __init__(self,filename,mode="r",encoding="utf-8"): self.file = open(filename,mode,encoding=encoding) self.mode = mode self.encoding = encoding def write(self,line): # print("--->",line) t = time.strftime("%Y-%m-%d %X") self.file.write("%s %s" %(t,line)) def __getattr__(self,item): # print(item,type(item)) # self.file.read return getattr(self.file,item) # getattr(self.file,item) f1 = FileHandle("a.txt","w+") print(f1.file)print("-->",f1.read)f1 = FileHandle("a.txt","w+")print(f1.file)print(f1.__dict__)print("-->",f1.read)print(f1.write) f.write("12345 ") f1.write("cpu负载过高 ") f1.write("内存剩余不足 ") f1.write("硬盘剩余不足 ") f1.seek(0) print("-->",f1.read)
9.os操作
9.1 逐行输出系统路径
print(sys.path) for i in sys.path: print(i)
9.2 获取版本号
print(sys.version)
9.3 更改当前工作目录,当前python脚本工作的目录路径
print(os.getcwd())
9.4 更改当前目录
os.chdir("D:\yuyukun")
9.5 在当前目录下创建多层子文件夹
os.makedirs(r"aabcc")
9.6 删除目录 如果当前目录下有文件,不删除
os.removedirs(r"aabcc")
9.7 以列表形式列出当前目录下所有文件和文件夹
print(os.listdir(os.getcwd()))
9.8 输出当前目录file信息,查看信息,用于上传信息
print(os.stat("file.py").st_size)
9.9 重命名文件夹包
os.rename("bb","ff")
9.10 显示所有信息
os.system("dir")
9.11 显示当前文件所在目录
print(__file__)
9.12 返回path规范化的绝对路径
print(os.path.abspath(__file__))
9.13 获取系统环境变量
os.environ
9.13 将文件所在目录分成目录和文件两部分
print(os.path.split(os.path.abspath(__file__)))
9.14 返回当前文件的上一级目录 必须是绝对路径
print(os.path.dirname(os.path.abspath(__file__)))
9.15 判断path是否存在,判断path的绝对路径是否存在,判断path是否有一个存在的目录,判断path是否是一个存在的目录
os.path.exists(path) os.path.isabs(path) os.path.isfile(path) os.path.isdir(path)
9.16 在__file__目录下新建aa文件夹,同时将123.txt文件附放到aa文件夹下,实现路径拼接
print(os.path.dirname(os.path.abspath(__file__))) print(os.path.join(os.path.dirname(os.path.abspath(__file__)),"aa","123.txt"))
10. item系列方法,查资料,理解资料,整理资料
class Foo: def __getitem__(self, item): print("getitem",item) return self.__dict__[item] def __setitem__(self, key, value): print("setitem") print('setitem') self.__delitem__[key] = value def __delitem__(self, key): print("delitem") self.__dict__.pop(key) f1 = Foo() print(f1.__dict__) f1["name"] = "alex" #字典方式设置,触发setitem f1[1] = "2222" f1["age"] = 18 del f1["name"] print(f1.__dict__) # del f1.name #不触发delitem() # print(f1.age) print(f1.__dict__) #总结:点方式操作属性,与实例有关,触发attr #[]方式操作属性,与系列有关,触发item
11.__str__和__repr__
str函数为打印输出函数,obj.__str__()
repr函数为交互式解释器,obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__代替输出
str和repr返回值必须字符串,否则输出异常
class Foo: def __init__(self,name,age): self.name = name self.age = age def __str__(self): return "名字是%s 年龄是%s" %(self.name,self.age) def __repr__(self): return "名字是%s 年龄是%s" %(self.name,self.age) f1 = Foo("alex",25) print(f1.__str__()) c = str(f1) print(c) print(f1) #以上三种写法相同 #str(f1)-----> f1.__str__()-----> f1.__repr__()
12.format表达形式,专门定制
format_dic={ "ymd":"{0.year}{0.mon}{0.day}", "m-d-y":"{0.mon}-{0.day}-{0.year}", "y:m:d":"{0.year}:{0.mon}:{0.day}" } class Date: def __init__(self,year,mon,day): self.year = year self.mon = mon self.day = day def __format__(self, format_spec): if not format_spec or format_spec not in format_dic: format_spec = "ymd" fm = format_dic[format_spec] return fm.format(self) d1 = Date("2019","04","09") print(format(d1,"ymd")) print(format(d1,"m-d-y")) print(format(d1,"y:m:d")) print(format(d1,"dfsdffdfsfd"))
13.slots属性: slots生成一种更为紧凑的内部表示,实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典, __slots__是定义在类中的类变量
class Foo: __slots__ = ["name","age"] # __slots__ = "name" f1 = Foo() # print(Foo.__slots__) # print(f1.__slots__) f1.name = "alex" f1.age = 17 #类中必须具有name和age这两个变量,否则报错 print(f1.name) print(f1.age) #类是一个共有事物,可以多次被调用 f2 = Foo() print(f2.__slots__) f2.name = "jason" f2.age=25 print(f2.name) print(f2.age)
14. del析构函数,整个实例被删除,触发函数
class Foo: def __init__(self,name): self.name = name def __del__(self): print("i am going on") f1 = Foo("alex") # del f1.name #整个实例被删除,触发函数 print("--------->")
15.__call__方法
__call__ 构造方法的执行是由创建对象触发的,即:对象=类名();对于__call__方法的执行是由队形后加括号触发的,即:对象()或者类()()
class Foo: def __call__(self, *args, **kwargs): print("实例执行啦 obj()") f1 = Foo() f1() #f1是一个实例,f1()调用的是Foo下的__call__方法 Foo() #Foo是一个类,Foo()对应有对象abc,Foo()调用的是abc下面的__call__方法
16. __iter__方法与__next__方法
__iter__生成迭代器,__next__执行迭代器,超过阈值,用raise抛出异常
#__next__与__iter__ class Foo: def __init__(self,n): self.n = n def __iter__(self): return self def __next__(self): self.n += 1 if self.n > 13: raise StopIteration return self.n f1 = Foo(10) print(f1.__next__()) print(f1.__next__()) print(f1.__next__()) print(next(f1))
例:斐波那契数列
class Fib: def __init__(self): self.a = 1 self.b = 1 def __iter__(self): return self def __next__(self): if self.a > 100: raise StopIteration("stop") else: self.a,self.b = self.b,self.a+self.b return self.a f1 = Fib() print(next(f1)) print(next(f1)) print(next(f1)) print(next(f1)) print(next(f1)) print("------------------>") for i in f1: print(i)
17.描述符有限级:
1类属性>2数据描述符>3实例属性>4非数据描述符>5找不到对象
class Foo: def __get__(self, instance, owner): print("--->get方法") def __set__(self, instance, value): print("--->方法",instance,value) instance.__dict__["x"]=value #对Bar.__dict__字典赋值 def __delete__(self, instance): print("--->delete方法") def __getattr__(self, item): print("can not find sth-------------------------------") class Bar: x = Foo() def __init__(self,n): self.x = n def __getattr__(self, item): print("can not find sth-------------------------------") # print(Bar.x) #类调用触发__get__方法 # Bar.x = 1 #赋值操作不触发__get__方法 # print(Bar.__dict__) # print(Bar.x) #实例属性,操作首先找数据描述符,其次找自己 # b1 = Bar() #类属性>数据描述符(描述符优先级) # b1.x #触发__get__方法 # b1.x = 1 #触发__set__ # del b1.x #触发__del__方法 b2 = Bar(10) print(b2.__dict__) #修改类实例------>12 b2.x = 12 #打开__set__方法,实例属性字典中为空;关闭__set__方法,实例属性字典有值 print(b2.__dict__) b2.xxxxxxxxxxxx #实例属性找不到,触发对应非数据描述符Bar的 __getattr__()
18.跨py文件(from...import...)操作,人为添加环境变量