一、xml
xml同Jason意义一样,不过较为过去式
示例m.xml内容:
2 2008 141100 5 2011 59900 69 2011 13600
搜索说明:
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()print(root.tag) #根标签print(root.attrib) #根属性print(root.text) #根内容print(root.iter('year')) #全文搜索print(root.find('country')) #在root的子节点查找,只查找一个print(root.findall('country')) #在root的子节点找,找所有
结果:
遍历xml内容
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()for child in root: print(child.tag,child.attrib,child.text) for i in child: print(i.tag,i.attrib,i.text)
显示结果:
遍历year节点:
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()for node in root.iter('year'): print(node.tag,node.text)
结果:
修改文件内容,给year内容加1:
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()for node in root.iter('year'): n_year=int(node.text)+1 node.text=str(n_year) node.set('updated','yes') #新增更新属性 node.set('version','2.0') #新增版本号属性tree.write('n.xml')
结果:
删除等级大于20的节点:
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()for country in root.findall('country'): # for rank in country.findall('rank'): #print(rank.tag,rank.attrib,rank.text) if int(rank.text) > 20: # country.remove(rank) #删除country的子节点 root.remove(country) #删除当前country节点tree.write('b.xml')
结果:
新增节点:
等于大于20的新增节点coincidence
import xml.etree.ElementTree as ETtree = ET.parse('m.xml')root = tree.getroot()for country in root.findall('country'): for rank in country.findall('rank'): if int(rank.text) > 20: kk=ET.Element('coincidence') #添加节点 kk.text='windfall' #添加节点内容 kk.attrib={ 'lottery':'22000000'} #添加节点属性 country.append(kk)tree.write('c.xml')
结果:
二、configparser
configparser修改类似于my.ini配置文件的内容,有自成的规律
示例文件:
[info1]name = 'ckl'age = 21hoppy = 'lang'is_young = Trueincome = 99999.22[info2]name = 'zld'age = 19hoppy = 'eat'is_young = Trueincome = 88888.33
获取操作
import configparser#导入模块,加载文件config = configparser.ConfigParser()config.read('ckl.ini')#打印所有标题res = config.sections()print(res)# ['info1', 'info2']#打印某个标题的所有keyops = config.options(config.sections()[0])print(ops)# ['name', 'age', 'hoppy', 'is_young', 'income']#打印某个标题的所有keyops1 = config.options('info2')print(ops1)# ['name', 'age', 'hoppy', 'is_young', 'income']#打印某个标题的所有key和valueitem_list = config.items('info1')for k,v in item_list: print(k,v)# name 'ckl'# age 21# hoppy 'lang'# is_young True# income 99999.22#获取section的name的值,字符串格式v1 = config.get('info1','name')print(v1)# 'ckl'#获取section的age的值,int格式v2 = config.getint('info1','age')print(type(v2))print(v2)## 21#获取section的is_young的值,布尔格式v3 = config.getboolean('info2','is_young')print(v3)# True#获取section的income的值,浮点格式v4 = config.getfloat('info1','income')print(v4)# 99999.22
删除操作
删除section
import configparserconfig = configparser.ConfigParser()config.read('ckl.ini')#删除section2config.remove_section('info2')config.write(open('ckl.ini','w')) #写入文件
结果:
删除info1的age
import configparserconfig = configparser.ConfigParser()config.read('ckl.ini')#删除info1的ageconfig.remove_option('info1','age')config.write(open('ckl.ini','w'))
结果:
判断存在section及option
import configparserconfig = configparser.ConfigParser()config.read('ckl.ini')#判断是否存在sectionprint(config.has_section('info1')) #True#判断是否存在某个keyprint(config.has_option('info1','age')) # False
添加一个section
import configparserconfig = configparser.ConfigParser()config.read('ckl.ini')#添加一个section及optionconfig.add_section('info3')config.set('info3','name','wukaka')config.set('info3','age','18')config.write(open('ckl.ini','w')) #添加内容必须是字符串格式
结果:
三、hashlib
1.hash是一种算法在python3以后,代替了MD5和sha模块,主要是:SHA1,SHA224,SHA256,SHA512,MD5等,传入内容,得到一串hash值
2.hash特点:
传入内容一样,得到值一样;不能又hash值反解内容;hash算法不变情况下,值一样。
import hashlibm5 = hashlib.md5()m5.update('nihao'.encode('utf8'))print(m5.hexdigest())# 194ce5d0b89c47ff6b30bfb491f9dc26m6 = hashlib.md5()m6.update('ni'.encode('utf8'))m6.update('hao'.encode('utf8'))print(m6.hexdigest())# 194ce5d0b89c47ff6b30bfb491f9dc26#使用md5算法,无论update多少次,内容一样,结果就一样
如何校验文件?
import hashlibm5 = hashlib.md5()with open('b.xml','r') as fread: for line in fread: m5.update(line.encode('utf8'))print(m5.hexdigest())# 8cb5a607e7803fd931112588e20e1f46#不推荐如此使用,耗费内存m6 = hashlib.md5()with open('b.xml','r') as fread: m6.update(fread.read().encode('utf8'))print(m6.hexdigest())# 8cb5a607e7803fd931112588e20e1f46
hashlib好用,但是可以撞库来反解,这个时候就需要加盐了salt
import hashlibh8 = hashlib.sha256('zthhk'.encode('utf8')) #add salth8.update('nihao'.encode('utf8'))print(h8.hexdigest())# 6eab55b060e7bc08c849a0b1405f4e7720271f10b8832b82a4c76ac47470c27c
hmac用法根其它类似,但是起始必须加盐
import hmach6 = hmac.new('bakayaro'.encode('utf8')) #类似加盐h6.update('nihao'.encode('utf8'))print(h6.hexdigest())# 6850656a1a3705600568152ff13e1195h7 = hmac.new('bakayaroni'.encode('utf8'))h7.update('hao'.encode('utf8'))print(h7.hexdigest())# d4891513a12338b58618516014ac9b25'''虽然两次的总的字符串内容一致,但结果却不一样。这是因为,生成值的时候,先匹配加盐的部分,再匹配update内容的部分,第一部分不一致,结果当然不一样'''
四、subprocess
运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。subprocess.call()
父进程等待子进程完成返回退出信息(returncode,相当于Linux exit code)subprocess.check_call()父进程等待子进程完成
返回0检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try…except…来检查subprocess.check_output()
父进程等待子进程完成返回子进程向标准输出的输出结果检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性和output属性,output属性为标准输出的输出结果,可用try…except…来检查。import subprocessres1 = subprocess.Popen('ls /Users/kindle/Desktop/',shell=True,stdout=subprocess.PIPE)res2 = subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE)print(res2.stdout.read())#这样做的好处是,第一个数据流可以和第二个数据流交互,并且交给grep
结果:
五、面向对象
对象是特征与功能的结合体;类是一系列对象相似特征与功能的结合体。
class WaterStaff: company = 'WaterLand' #类的数据属性(静态属性) def work(self): #类的函数属性(动态属性) print('we are working') def sleep(self): print('go home and sleep')#从本质上查看类的所有属性,print(WaterStaff.__dict__)#访问类的属性print(WaterStaff.company)print(WaterStaff.sleep)# WaterLand##新增类的属性WaterStaff.company = 'CKL'print(WaterStaff.company)# CKL#修改类的属性WaterStaff.tech = 'niux'print(WaterStaff.tech)# niux#删除类的某个属性del WaterStaff.tech
对象
#产生程序中的对象:类名加括号,调用类,产生一个该类的实际存在的对象,该调用过程称为实例化,产生的结果又可以称为实例。obj1 = WaterStaff()
对象实例化
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #在实例化时,产生对象后执行 self.name = name self.age = age self.gender = gender #上面实际就是如下: # obj1.name = '雪山人' # obj1.age = 25 # obj1.gender = 'male' def work(self): print('we are working') def sleep(self): print('go home and sleep')obj1 = WaterStaff('雪山人',25,'male')#执行两步#1.先产生空对象obj1#2.WaterStaff.__init__(obj1,'雪山人',25,'male'),这里self就是对象本身print(obj1.__dict__)# {'name': '雪山人', 'age': 25, 'gender': 'male'}
对象属性操作
#修改属性obj1.name = '森林人'print(obj1.name)# 森林人#新增属性obj1.car = 'horse'print(obj1.car)# horse#当然也可以如下修改obj1.__dict__['age'] = 22print(obj1.age)# 22print(obj1.__dict__)# {'name': '森林人', 'age': 22, 'gender': 'male', 'car': 'horse'}
__init__不仅可以为对象初始化属性,还可以定时任何方法
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #如果name不是字符串,就抛出异常 if not isinstance(name,str): raise TypeError('name must be a tye of string') self.name = name self.age = age self.gender = gender def work(self): print('we are working') def sleep(self): print('go home and sleep')obj1 = WaterStaff(889,25,'male')
__init__()函数return None
类的数据属性(静态属性)
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #如果name不是字符串,就抛出异常 if not isinstance(name,str): raise TypeError('name must be a tye of string') self.name = name self.age = age self.gender = gender def work(self): print('we are working') def sleep(self): print('go home and sleep')obj1 = WaterStaff('雪山人',25,'male')obj2 = WaterStaff('森林人',33,'male')obj3 = WaterStaff('原野人',22,'female')#对象可以访问类的数据属性(静态属性);结论:类的数据属性共享给所有对象使用,id一样print(obj1.company,id(obj1.company))print(obj2.company,id(obj2.company))print(obj3.company,id(obj3.company))print(WaterStaff.company,id(WaterStaff.company))# WaterLand 4368851632# WaterLand 4368851632# WaterLand 4368851632# WaterLand 4368851632
类的函数属性(动态属性)
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #如果name不是字符串,就抛出异常 if not isinstance(name,str): raise TypeError('name must be a tye of string') self.name = name self.age = age self.gender = gender def work(self): print('%s are working' %self.name) #objx.name def sleep(self): print('go home and sleep')obj1 = WaterStaff('雪山人',25,'male')obj2 = WaterStaff('森林人',33,'male')obj3 = WaterStaff('原野人',22,'female')WaterStaff.work(obj1)WaterStaff.work(obj2)WaterStaff.work(obj3)# 雪山人 are working# 森林人 are working# 原野人 are working
绑定方法
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #如果name不是字符串,就抛出异常 if not isinstance(name,str): raise TypeError('name must be a tye of string') self.name = name self.age = age self.gender = gender def work(self): print('%s are working' %self.name) #objx.name def sleep(self): print('go home and sleep')obj1 = WaterStaff('雪山人',25,'male')obj2 = WaterStaff('森林人',33,'male')obj3 = WaterStaff('原野人',22,'female')print(obj1.work)print(obj2.work)print(obj3.work)print(WaterStaff.work)#除了类本身,其它对象的函数属性,都是绑定给其本身,绑定方法#># ># ># #绑定方法:绑定给谁,就由谁来调用,谁来调用就把"谁"本身当做第一个参数传入obj1.work() #WaterStaff.work(obj1)# 雪山人 are working
python3的类型
#python3 类型就是类l1 = list()l2 = list()l1.append(3) #list.append(l1,3)print(l1) # [3]print(l2) # []
属性访问顺序
class WaterStaff: company = 'WaterLand' def __init__(self,name,age,gender): #如果name不是字符串,就抛出异常 if not isinstance(name,str): raise TypeError('name must be a tye of string') self.name = name self.age = age self.gender = gender def work(self): print('%s are working' %self.name) #objx.name def sleep(self): print('go home and sleep')obj1 = WaterStaff('雪山人',25,'male')obj2 = WaterStaff('森林人',33,'male')obj3 = WaterStaff('原野人',22,'female')#访问实例属性print(obj1.__dict__) #{'name': '雪山人', 'age': 25, 'gender': 'male'}print(obj1.company) # WaterLand#修改obj1的数据属性obj1.company = 'LandW'print(obj1.company) #LandWprint(obj2.company) #WaterLand#修改类本身的数据属性WaterStaff.company = 'wukaka'print(obj1.company) #LandW #obj1已经修改了自己的数据属性print(obj2.company) #wukaka
类交互:
#怪物牛class BullEv: # 怪物牛名称、血量、攻击力 def __init__(self,nickname,blvom=100,aggressivity=80): self.nickname = nickname self.blvom = blvom self.aggressivity = aggressivity #攻击技能,血量等于自己攻击力减去对方血量 def attack(self,rival): rival.blvom-=self.aggressivity#怪物蜘蛛class SpiderEv: #怪物蜘蛛名称、血量、攻击力 def __init__(self,nickname,blvom=80,aggressivity=100): self.nickname = nickname self.blvom = blvom self.aggressivity = aggressivity # 攻击技能,血量等于自己攻击力减去对方血量 def attack(self,rival): rival.blvom -= self.aggressivityB1=BullEv('wukaka')S1=SpiderEv('Bengde')#攻击前血量print('attack before ------>',S1.blvom)B1.attack(S1)#攻击后血量print('after attack------->',S1.blvom)
结果:
上面类有重复代码,如何解决?那么久看看类的继承
类的继承
class ParentClass1: #定义父类 passclass ParentClass2: #定义父类 passclass SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass passclass SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
继承:
#继承一个父类print(SubClass1.__bases__) #(,)#继承两个父类print(SubClass2.__bases__) #(
继承与重用
人、鸟、兔子,都有吃、叫、睡觉的功能创建三个类
class Mankind: def eat(self): print("eat something") def talk(self): print("talk something")class Bird: def eat(self): print("eat something") def talk(self): print("talk something")class Rabbit: def eat(self): print("eat something") def talk(self): print("talk something")M1 = Mankind()M1.eat()B1 = Bird()B1.eat()
运行结果:
继承父类
问题:吃、说的功能重复代码,是否可以继承?改写如下:
class Animal: def eat(self): print("eat something") def talk(self): print("talk something")class Mankind(Animal): passclass Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind()M1.eat()B1 = Bird()B1.eat()
结果:
问题二、每个子类应该有自己的名字年龄等信息,修改如下:
class Animal: def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender): self.name = name self.age = age self.gender = genderclass Bird(Animal): def __init__(self,name,age,gender): self.name = name self.age = age self.gender = genderclass Rabbit(Animal): def __init__(self,name,age,gender): self.name = name self.age = age self.gender = genderM1 = Mankind('wukaka',33,'male')M1.eat()B1 = Bird('flygo',3,'female')B1.eat()
运行结果:
问题三、这三个子类有共同的属性名字、年龄,性别等,重写如下:
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): passclass Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male')M1.eat()B1 = Bird('flygo',3,'female')B1.eat()
结果相同:
重用
人类还有国籍,所以定义如下:
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): self.name = name self.age = age self.gender = gender self.native = nativeclass Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male','china')print(M1.__dict__) #{'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china'}M1.eat()B1 = Bird('flygo',3,'female')B1.eat()
这样,如下部分就与父类重复:
self.name = name self.age = age self.gender = gender
改写如下:
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): Animal.__init__(self,name,age,gender) #改写部分 self.native = nativeclass Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male','china')print(M1.__dict__) #{'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china'}M1.eat()B1 = Bird('flygo',3,'female')B1.eat()
这样实际上指明父类调用,根继承无关,结果:
派生新的属性
人有一个自己说的方法,如下:
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): Animal.__init__(self,name,age,gender) #改写部分 self.native = native def takl(self): print('*** a chinese man is saying')class Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male','china')print(M1.__dict__) #{'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china'}M1.eat()M1.takl()B1 = Bird('flygo',3,'female')B1.eat()
结果:
如果人talk的方法也想用父类的talk呢?
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): Animal.__init__(self,name,age,gender) #改写部分 self.native = native def takl(self): Animal.talk(self) #调用父类的 print('*** a chinese man is saying')class Bird(Animal): passclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male','china')print(M1.__dict__) #{'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china'}M1.eat()M1.takl()B1 = Bird('flygo',3,'female')B1.eat()
结果:
组合
一个人可以有多个房子,房子有地址、面积、价格,一个鸟也可以有多个窝,窝也有地址、面积、价格等,如下:
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native,house_addr,house_area,house_price): Animal.__init__(self,name,age,gender) self.native = native self.house_addr = house_addr self.house_area = house_area self.house_price = house_price def takl(self): Animal.talk(self) print('*** a chinese man is saying')class Bird(Animal): def __init__(self,name,age,gender,house_addr,house_area,house_price): Animal.__init__(self,name,age,gender) self.house_addr = house_addr self.house_area = house_area self.house_price = house_priceclass Rabbit(Animal): passM1 = Mankind('wukaka',33,'male','china','pudong','120','12000000')print(M1.__dict__)B1 = Bird('flygo',3,'female','nanhui','0.01','10')print(B1.__dict__)
运行:
{ 'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china', 'house_addr': 'pudong', 'house_area': '120', 'house_price': '12000000'}{ 'name': 'flygo', 'age': 3, 'gender': 'female', 'house_addr': 'nanhui', 'house_area': '0.01', 'house_price': '10'}
这里人的房子和鸟的窝就出现重复代码,如果人有多个房子,鸟有多个窝呢?如何实现?
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): Animal.__init__(self,name,age,gender) self.native = native #定义house列表 self.house = [] def takl(self): Animal.talk(self) print('*** a chinese man is saying')class Bird(Animal): def __init__(self,name,age,gender,): Animal.__init__(self,name,age,gender) #定义house列表 self.house = []#定义house类class House: #定义house_addr,house_area,house_price def __init__(self,house_addr,house_area,house_price): self.house_addr = house_addr self.house_area = house_area self.house_price = house_price #定义个函数属性,来显示house相关信息 def show_info(self): print("house address: %s house area: %s house price %s" %(self.house_addr,self.house_area,self.house_price))class Rabbit(Animal): pass#实例化第一个househouse1 = House('pudong','109','11000000')#实例化第二个househouse2 = House('putuo','98','9900000')M1 = Mankind('wukaka',33,'male','china')#为人类添加两个houseM1.house.append(house1)M1.house.append(house2)print(M1.__dict__)# {'name': 'wukaka', 'age': 33, 'gender': 'male', 'native': 'china', 'house': [<__main__.House object at 0x109dfa048>, <__main__.House object at 0x109dfa080>]}#循环人类house,也就是对象house1和house2for obj in M1.house: obj.show_info() #调用对象函数
结果:
组合实现了不同类有相同的属性,但不需要从父类继承的操作。
继承原理
单继承说明
class A: def f1(self): print("A.f1") def f2(self): self.f1()class B(A): def f1(self): print("B.f1")obj_b = B()obj_b.f2()
结果:
B.f1
分析:1.初始化类B。2.调用B类的实例化对象,运行方法f2()。3.找B类f2(),没有找到,则找继承的父类A。4.A类有方法f2(),调用方法f2,f2()则调用self.f1()。self本身就是B类,所以查找B的方法f1()有找到,则执行,结果就是B.f1
super 调用父类
super 调用父类静态属性
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): # Animal.__init__(self,name,age,gender) #这是直接调用父类的,不是继承 # super() 是父类对象的实例 # print(super().__init__) #实例化父类,绑定方法,绑定其本身,所以调用父类的新写法 super().__init__(name,age,gender) #其本身已经是绑定方法,所以不需要self self.native = native def takl(self): Animal.talk(self) #调用父类的 print('*** a chinese man is saying')M1 = Mankind('wukaka',33,'male','china')M1.eat()
结果:
wukaka eat something
super 调用父类动态属性
class Animal: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def eat(self): print("%s eat something" %self.name) def talk(self): print("talk something")class Mankind(Animal): def __init__(self,name,age,gender,native): # Animal.__init__(self,name,age,gender) #这是直接调用父类的,不是继承 # super() 是父类对象的实例 # print(super().__init__) #实例化父类,绑定方法,绑定其本身,所以调用父类的新写法 super().__init__(name,age,gender) #其本身已经是绑定方法,所以不需要self self.native = native def takl(self): # Animal.talk(self) #调用父类的动态属性,不是继承 super().eat() #super 调用父类动态属性的写法 print('*** a chinese man is saying')M1 = Mankind('wukaka',33,'male','china')M1.eat()
结果:
wukaka eat something
区别:super()依赖于继承,而直接调用不依赖继承
Animal.talk(self) #不依赖父类继承 super().eat() #super 依赖父类继承
super() 查找的是MRO列表:
[, , ]
关于MRO列表查找疑惑
class A: def test(self): super().test()class B: def test(self): print("B")class C(A,B): def test(self): print("C")obj_a = A()obj_a.test()
运行:
分析:1.实例化A类。2.A类对象调用动态属性test()。3.A类的test调用super().test(),也就是父类的test(),而A类没有父类,所以报错。
如果这样运行:
class A: def test(self): super().test()class B: def test(self): print("B")class C(A,B): passobj_c = C()obj_c.test()
会不会报错?答案是不会,而且结果是
B
是不是迷惑了?分析如下:
1.实例化C类。2.实例化对象调用test。3.C类没有test,找父类A,父类A有test。4.A类调用test的时候调用的是super().test(),这时候,super()就不是找父类了,而是查找MRO列表的顺序,接下来查找B类,B类有方法test(),所以运行B类的test
print(C.mro())# [, , , ]
classmethod
classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
看一个示例:
class Mysql: def __init__(self,host,port): self.host = host self.port = portconn1=Mysql('127.0.0.1',3306)print(conn1.port,conn1.host)
运行结果:
如果每次都需要传入地址、端口等参数,很麻烦,有没有办法可以从配置文件中读取?
配置文件内容:
HOST='10.2.3.4'PORT=8898
代码:
import settingsclass Mysql: def __init__(self,host,port): self.host = host self.port = port @classmethod def from_conf(cls): #这个方法绑定给类 return cls(settings.HOST,settings.PORT)conn1=Mysql('127.0.0.1',3306)print(conn1.port,conn1.host)conn2=Mysql.from_conf()#Mysql.from_conf是绑定方法,绑定给谁就给谁用,给谁用就把自己当做第一个参数print(conn2.host,conn2.port)
运行结果:
方法绑定说明
import settingsclass Mysql: def __init__(self,host,port): self.host = host self.port = port @classmethod def from_conf(cls): #绑定给类的方法 return cls(settings.HOST,settings.PORT) def func1(self): #绑定给对象的方法 passconn1=Mysql('127.0.0.1',3306)# print(conn1.port,conn1.host)# conn2=Mysql.from_conf()# #Mysql.from_conf是绑定方法,绑定给谁就给谁用,给谁用就把自己当做第一个参数# print(conn2.host,conn2.port)print(conn1.from_conf)print(conn1.func1)
结果说明:
staticmethod
import settingsimport uuidclass Mysql: def __init__(self,host,port): self.host = host self.port = port self.id = self.create_id() @staticmethod def create_id(): #普通方法,既不绑定给对象,也不绑定给类 return uuid.uuid1()conn1=Mysql('127.0.0.1',3306)conn2=Mysql('127.0.0.1',3306)conn3=Mysql('127.0.0.1',3306)print(conn1.id,conn2.id,conn3.id)print(Mysql.create_id) #普通函数print(conn1.create_id) #普通函数
结果:
class School: def __init__(self,school_name,school_address): self.school_name = school_name self.school_address = school_addressclass Course(School): def __init__(self,course_name,course_period,couse_price,course_outline): self.course_name = course_name self.course_period = course_period self.course_price = couse_price self.course_outline = course_outline def get_school(self,school): return school.__dict__class ClassG(Course): def __init__(self,class_name): self.class_name = class_name def get_course(self,course): return (course.__dict__,self.class_name)class Student(ClassG): def __init__(self,student_name): self.student_name = student_nameclass Teacher(ClassG): def __init__(self,teacher_name,): self.teacher_name = teacher_nameclass TeachRecord: passclass StudyRecord: passs1=School('mazhu','pudong')c1=Course('python',120,8990,[4,6,7,8])g1=ClassG('19s')st1=Student('whb')print(st1.get_course(g1))