当前位置: 首页 > news >正文

第七 其它模块及面向对象

一、xml

xml同Jason意义一样,不过较为过去式

示例m.xml内容:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

搜索说明:

import xml.etree.ElementTree as ET

tree = 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 ET

tree = 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 ET

tree = 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 ET

tree = 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 ET

tree = 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 ET

tree = 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 = 21
hoppy = 'lang'
is_young = True
income = 99999.22

[info2]
name = 'zld'
age = 19
hoppy = 'eat'
is_young = True
income = 88888.33

获取操作

import configparser

#导入模块,加载文件
config = configparser.ConfigParser()
config.read('ckl.ini')

#打印所有标题
res = config.sections()
print(res)
# ['info1', 'info2']

#打印某个标题的所有key
ops = config.options(config.sections()[0])
print(ops)
# ['name', 'age', 'hoppy', 'is_young', 'income']

#打印某个标题的所有key
ops1 = config.options('info2')
print(ops1)
# ['name', 'age', 'hoppy', 'is_young', 'income']

#打印某个标题的所有key和value
item_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)
# <class 'int'>
# 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 configparser
config = configparser.ConfigParser()
config.read('ckl.ini')

#删除section2
config.remove_section('info2')
config.write(open('ckl.ini','w'))  #写入文件

结果:

删除info1的age

import configparser
config = configparser.ConfigParser()
config.read('ckl.ini')


#删除info1的age
config.remove_option('info1','age')
config.write(open('ckl.ini','w'))

结果:

判断存在section及option

import configparser
config = configparser.ConfigParser()
config.read('ckl.ini')

#判断是否存在section
print(config.has_section('info1')) #True
#判断是否存在某个key
print(config.has_option('info1','age')) # False

添加一个section

import configparser
config = configparser.ConfigParser()
config.read('ckl.ini')

#添加一个section及option
config.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 hashlib

m5 = hashlib.md5()
m5.update('nihao'.encode('utf8'))
print(m5.hexdigest())
# 194ce5d0b89c47ff6b30bfb491f9dc26

m6 = hashlib.md5()
m6.update('ni'.encode('utf8'))
m6.update('hao'.encode('utf8'))
print(m6.hexdigest())
# 194ce5d0b89c47ff6b30bfb491f9dc26


#使用md5算法,无论update多少次,内容一样,结果就一样

 如何校验文件?

import hashlib
m5 = 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 hashlib
h8 = hashlib.sha256('zthhk'.encode('utf8')) #add salt
h8.update('nihao'.encode('utf8'))
print(h8.hexdigest())
# 6eab55b060e7bc08c849a0b1405f4e7720271f10b8832b82a4c76ac47470c27c

hmac用法根其它类似,但是起始必须加盐

import hmac
h6 = hmac.new('bakayaro'.encode('utf8')) #类似加盐
h6.update('nihao'.encode('utf8'))
print(h6.hexdigest())
# 6850656a1a3705600568152ff13e1195

h7 = 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 subprocess

res1 = 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

结果:

https://docs.python.org/2/library/subprocess.html

五、面向对象

对象是特征与功能的结合体;类是一系列对象相似特征与功能的结合体。

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
# <function WaterStaff.sleep at 0x10149c378>

#新增类的属性
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'] = 22
print(obj1.age)
# 22

print(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)

#除了类本身,其它对象的函数属性,都是绑定给其本身,绑定方法
# <bound method WaterStaff.work of <__main__.WaterStaff object at 0x104f83ba8>>
# <bound method WaterStaff.work of <__main__.WaterStaff object at 0x104f83be0>>
# <bound method WaterStaff.work of <__main__.WaterStaff object at 0x104f83c18>>
# <function WaterStaff.work at 0x104f87378>

#绑定方法:绑定给谁,就由谁来调用,谁来调用就把"谁"本身当做第一个参数传入
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)  #LandW
print(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.aggressivity

B1=BullEv('wukaka')
S1=SpiderEv('Bengde')

#攻击前血量
print('attack before ------>',S1.blvom)
B1.attack(S1)
#攻击后血量
print('after attack------->',S1.blvom)

结果:

 上面类有重复代码,如何解决?那么久看看类的继承

 类的继承

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

继承:

#继承一个父类
print(SubClass1.__bases__) #(<class '__main__.ParentClass1'>,)

#继承两个父类
print(SubClass2.__bases__) #(<class

继承与重用

人、鸟、兔子,都有吃、叫、睡觉的功能创建三个类

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):
    pass

class Bird(Animal):
    pass

class Rabbit(Animal):
    pass

M1 = 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 = gender

class Bird(Animal):
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

class Rabbit(Animal):
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

M1 = 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):
    pass

class Bird(Animal):
    pass

class Rabbit(Animal):
    pass

M1 = 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 = native

class Bird(Animal):
    pass

class Rabbit(Animal):
    pass

M1 = 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 = native

class Bird(Animal):
    pass

class Rabbit(Animal):
    pass

M1 = 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):
    pass

class Rabbit(Animal):
    pass

M1 = 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):
    pass

class Rabbit(Animal):
    pass

M1 = 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_price

class Rabbit(Animal):
    pass

M1 = 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

#实例化第一个house
house1 = House('pudong','109','11000000')
#实例化第二个house
house2 = House('putuo','98','9900000')

M1 = Mankind('wukaka',33,'male','china')
#为人类添加两个house
M1.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和house2
for 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列表:

[<class '__main__.Mankind'>, <class '__main__.Animal'>, <class 'object'>]

关于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):
    pass

obj_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())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

classmethod 

classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

看一个示例:

class Mysql:
    def __init__(self,host,port):
        self.host = host
        self.port = port

conn1=Mysql('127.0.0.1',3306)
print(conn1.port,conn1.host)

运行结果:

如果每次都需要传入地址、端口等参数,很麻烦,有没有办法可以从配置文件中读取?

配置文件内容:

HOST='10.2.3.4'
PORT=8898

代码:

import settings

class 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 settings

class 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): #绑定给对象的方法
        pass

conn1=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 settings
import uuid

class 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_address

class 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_name

class Teacher(ClassG):
    def __init__(self,teacher_name,):
        self.teacher_name = teacher_name

class TeachRecord:
    pass

class StudyRecord:
    pass

s1=School('mazhu','pudong')
c1=Course('python',120,8990,[4,6,7,8])
g1=ClassG('19s')
st1=Student('whb')
print(st1.get_course(g1))

 

转载于:https://www.cnblogs.com/ckl893/p/7002199.html

相关文章:

  • 【JavaScript】explode动画
  • 花了 4 个月整理了 50 篇 Android 干货文章
  • centos7 双网卡双ip内外网设置最小化安装
  • 移动端web app开发备忘
  • 人生最重要的三种能力,不是读书能学来的
  • 解密浏览器缓存机制
  • OGG运维优化脚本(五)-信息修改类--批量注释
  • 拥抱PBO(基于项目的组织)聚焦核心价值创造
  • awk条件语句
  • ES5新特性
  • MySQL用命令行复制表,查看表结构
  • java并发之TimeUnit理解
  • spring定时任务
  • 读《十亿美金的教训》看中国传奇人物
  • TCP端口状态说明ESTABLISHED、TIME_WAIT
  • Android开源项目规范总结
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • Invalidate和postInvalidate的区别
  • log4j2输出到kafka
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • nodejs实现webservice问题总结
  • Objective-C 中关联引用的概念
  • Python语法速览与机器学习开发环境搭建
  • TypeScript迭代器
  • V4L2视频输入框架概述
  • 阿里云前端周刊 - 第 26 期
  • 从零开始学习部署
  • 前端性能优化——回流与重绘
  • 数据结构java版之冒泡排序及优化
  • 学习使用ExpressJS 4.0中的新Router
  • 一、python与pycharm的安装
  • 阿里云重庆大学大数据训练营落地分享
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​Spring Boot 分片上传文件
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #{}和${}的区别?
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (09)Hive——CTE 公共表达式
  • (2)STL算法之元素计数
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (八)Spring源码解析:Spring MVC
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (多级缓存)多级缓存
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET : 在VS2008中计算代码度量值
  • .NET C# 使用 iText 生成PDF
  • .Net Core和.Net Standard直观理解
  • .NET 给NuGet包添加Readme
  • .Net实现SCrypt Hash加密
  • :如何用SQL脚本保存存储过程返回的结果集
  • [].slice.call()将类数组转化为真正的数组
  • [100天算法】-每个元音包含偶数次的最长子字符串(day 53)
  • [1181]linux两台服务器之间传输文件和文件夹