多态,封装,反射,类内置attr属性,os操作复习

时间:2023-08-15 21:08:38

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("","alex","",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("","alex","",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”
# 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文件;

运行程序;

多态,封装,反射,类内置attr属性,os操作复习

图1 B中处理的工作

多态,封装,反射,类内置attr属性,os操作复习

图2 A中运行程序的结果

多态,封装,反射,类内置attr属性,os操作复习

图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.动态模块导入_*模块名和当前模块名区别

*模块可调用函数中内容

当前模块不能调用函数中内容

多态,封装,反射,类内置attr属性,os操作复习

图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\n")
f1.write("cpu负载过高\n")
f1.write("内存剩余不足\n")
f1.write("硬盘剩余不足\n")
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"aa\bb\cc")

9.6 删除目录 如果当前目录下有文件,不删除

os.removedirs(r"aa\bb\cc")

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] = ""
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("","","")
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...)操作,人为添加环境变量

多态,封装,反射,类内置attr属性,os操作复习