python学习生涯 day10-16

0 os模块:一个与操作系统有关的模块

在这里插入图片描述
这个模块内容很多,切忌死记硬背,需要使用的时候查询即可

1 sys模块:一个与python解释器有关的模块

在这里插入图片描述
使用同上

2 序列化模块

序列化:将其他数据类型转化成字符串类型(一般用于写文件和网络传输中)
反序列化:将字符串类型转化成其他数据类型
序列化模块主要有json模块,pickle模块,shelve模块,接下来将一一讲解:
0)json模块:通用的序列化格式,只有一小部分数据类型可以通过json模块转换成字符串类型,json模块一般有4种方法:dumps();loads();dump();load()
dumps()和loads()的使用:
import json

dic = {'a': '100', 'b': '20'}
lis = json.dumps(dic)
print(lis, type(lis))
dic_ = json.loads(lis)
print(dic_, type(dic_))

在这里插入图片描述
dump()和load()的使用:(对文件句柄进行操作)
json.dump()用于将dict类型的数据转成str,并写入到json文件中。
json.load()用于从json文件中读取数据。

import json
dic = {'a': '100', 'b': '20'}
with open('fff.txt', 'w', encoding='utf-8') as f:
    json.dump(dic, f)

#如果字典中有中文,稍微有所变化

import json
dic = {'a': '中国', 'b': '20'}
with open('fff.txt', 'w', encoding='utf-8') as f:
    json.dump(dic, f, ensure_ascii=False)
 

注意:dump和load一次只能处理一个字典,如果需要多次,必须绕过dump和load

import json
l = [{'k1': '111'}, {'k2': '111'}]
f = open('ttt.txt', 'w')
for i in l:
    str_dic = json.dumps(i)
    f.write(str_dic + '\n')
f.close()

在这里插入图片描述

f = open('ttt.txt')
new_l = []
for line in f:
    dic = json.loads(line)
    new_l.append(dic)
f.close()
  1. pickle模块:所有的数据类型都能通过pickle模块转化成字符串数据类型,但是pickle序列化后的内容只有python才能理解,且部分反序列化依赖python代码(这句话目前不能理解)
    pickle模块和json一样,同样提供了dumps();loads();dump();load()方法,但是在使用过程中稍微有所区别
    在dump()的时候必须以‘wb’的方式打开 ,在load()的时候必须以‘rb’的方式打开
import pickle
dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
str_dic = pickle.dumps(dic)
print(str_dic, type(str_dic))  #一串二进制内容

dic2 = pickle.loads(str_dic)
print(dic2, type(dic2)) 

一个关于dump和load的使用案例:

import pickle
import time
struct_time = time.localtime(1000000000)
print(struct_time)
f = open('pickle_file', 'wb')
pickle.dump(struct_time, f)
f.close()

f = open('pickle_file', 'rb')
struct_time2 = pickle.load(f)
print(struct_time2.tm_year)

2) shelve模块:这个模块目前不太成熟,了解即可

3 模块

0)模块的导入
当导入一个模块时,先从sys.modules中看是否被导入,如果没有被导入,就从sys.path路径寻找模块,再创建这个模块的命名空间,把文件中的名字全部放到命名空间上去,这也就是模块不会被重复导入的原因
1)模块的别名
当几个模块执行的功能相同时,可以将这几个模块起同一个别名,这样使用起来就会很方便
2)模块的顺序
导入模块时,要将模块写在程序的最开始,且最好使用
import a
import b
import c
不推荐使用 import a, b, c
顺序一般为:

内置模块

扩展模块

自己写的模块
3)从某个模块中调用某个方法
from a import b
比如:from time import sleep

关于模块的小结:

import 模块名
模块名.方法名 和本文件中的变量名完全不冲突

import 模块名 as 重命名的模块名
#提高代码的兼容性

from 模块名 import 方法名
#直接使用方法名就可以完成操作
#如果本文件中有相同的变量名会发生冲突
#from 模块名 import 变量名 as 重命名的变量名

from 模块名 import 方法名1,方法名2
from 模块名 import *
#将模块中的所有方法名都放到内存中
#如果本文件中有相同的变量名会发生冲突

#import * 和__all__是一对
如果没有__all__, 模块里面的所有方法都被导入
如果有__all__, __all__里有的方法会被导入

在模块中,有一个变量__name__
当我们直接执行这个模块的时候,name == ‘main
当我们在其他模块中引用这个模块的时候,name == ‘模块名

与上文无关,但是关于__name__ == 'main’有点想要补充的
这句话是python程序的入口,相当于c语言中的main函数

4 包

包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
一个完整的python程序通常不只包含一个python文件,一个完整的python程序如下所示:
在这里插入图片描述

conf里面放配置文件,让用户可以看懂的
core 核心代码
db 数据
lib 自己写的模块
log 记录的过程
当调用python包时,会自动执行该包下的__init__文件

os.makedirs('glance/api')
os.makedirs('glance/cmd')
os.makedirs('glance/db')
l = []
l.append(open('glance/__init__.py','w'))
l.append(open('glance/api/__init__.py','w'))
l.append(open('glance/api/policy.py','w'))
l.append(open('glance/api/versions.py','w'))
l.append(open('glance/cmd/__init__.py','w'))
l.append(open('glance/cmd/manage.py','w'))
l.append(open('glance/db/models.py','w'))
l.append(open('glance/db/__init__.py','w'))
map(lambda f:f.close() ,l)

在这里插入图片描述

#文件内容

#policy.py
def get():
    print('from policy.py')

#versions.py
def create_resource(conf):
    print('from version.py: ',conf)

#manage.py
def main():
    print('from manage.py')

#models.py
def register_models(engine):
    print('from models.py: ',engine)

执行get文件的两种方法:
import glance.api.policy
glance.api.policy.get()
from glance.api.policy import get
get()在这里插入图片描述
如果想调用import glance 然后使用policy versions等功能怎么办呢?
在glance的__init__文件里导入如下模块,利用了自动执行__init__这个功能
from glance import api
from glance import cmd
from glance import db
分别在api,cmd,db的__init__文件里导入如下模块
from glance.api import policy
from glance.api import versions
————————————————
from glance.cmd import manage

————————————————
from glance.db import models

经过尝试
import glance
glance.api.policy.get()在这里插入图片描述
例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py

#在glance/api/version.py

#绝对导入
from glance.cmd import manage
manage.main()

#相对导入
from ..cmd import manage
manage.main()

5 异常处理

try:
    ret = int(input('number>>>>>'))
    print(ret*'*')
except ValueError:
    print('你的输入有误,请输入一个数字')
except Exception:
    print('抗压吧务团队1')
else:
    print('---------')
finally:
    print('nmsl')

当程序执行遇到错误时,后面的程序就不会执行
#使用try和except就能处理异常
#try是我们需要处理的代码
#except后跟一个错误类型,当代码发生错误且类型相同时,就会执行except的内容
#except 支持多分支(进行一个分支后就不会进入其他分支,在上述程序中,如果发生ValueError,就不会进入Exception)
有没有一个能处理所有错误的类型:Exception
#有了万能的处理机制仍然需要将能预测到的错误单独讨论
#单独处理的内容必须放在万能异常前面
#else:没有异常时会执行else的代码
#finally;不管代码是否异常,都会执行
#finally和return相遇的时候,仍然会执行
#做一些收尾工作

一个简单的程序:

c = []
while True:
    a = input('请输入数字(退出请输入b):')
    if a == 'b':
        break
    else:
        try:
            c.append(int(a))
        except Exception as e:
            print('你存在如下错误', e)
print(sum(c))
print(len(c))
print(sum(c)/len(c))

6 面向对象三大特性之继承

0)一个类可以被多个类继承
1)一个类可以继承多个负类(多继承),只在python中存在
2)在python3中,所有的类都有其父类,如果没有继承,默认它的父类就是object(顶级类)

class A:
    pass


class B(A):
    pass


print(A.__base__)
print(B.__base__)

.__base__方法可以查询父类在这里插入图片描述

如何更形象地理解继承?
在这里插入图片描述

class Animal:
    def __init__(self, name, hp, aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr


class Person(Animal):
    def __init__(self, name, hp, aggr, sex):
        Animal.__init__(self, name, hp, aggr)
        self.sex = sex  # 派生属性
        self.money = 0  # 派生属性

    def attack(self, dog):
        dog.hp -= self.aggr


class Dog(Animal):
    def __init__(self, name, hp, aggr, kind):
        Animal.__init__(self, name, hp, aggr)
        self.kind = kind  # 派生属性

    def bite(self, person):
        person.hp -= self.aggr


jin = Dog('泰迪', 500, 200, '看家')
alex = Person('陈叔', 999, 111, '男')
print(jin.kind)
print(alex.sex)

小结:
当在自己的类中找不到__init__时,就会到父类里面找__init__
子类中有而父类中没有的属性,叫做派生属性
子类中有而父类中没有的方法, 叫做派生方法
当调用时,先再子类里面找,找不到再在父类里面找
既想实现新的功能,又想调用父类的功能,就需要在子类中调用父类的功能(上述的代码就用了这点,建议好好研究)

一个关于super()的实例:

class A:
    def hahaha(self):
        print('A')


class B(A):
    def hahaha(self):
        super().hahaha()
        print('B')


a = A()
b = B()
b.hahaha()

在这里插入图片描述
子类调用父类的方法时,可以使用super() 这种方法可以少传入一个self参数

class Animal:
    def __init__(self, name, hp, aggr):
        self.name = name
        self.hp = hp
        self.aggr = aggr


class Person(Animal):
    def __init__(self, name, hp, aggr, sex):
        super().__init__(name, hp, aggr)
        self.sex = sex  # 派生属性
        self.money = 0  # 派生属性

    def attack(self, dog):
        dog.hp -= self.aggr


class Dog(Animal):
    def __init__(self, name, hp, aggr, kind):
        super().__init__(name, hp, aggr)
        self.kind = kind  # 派生属性

    def bite(self, person):
        person.hp -= self.aggr


jin = Dog('泰迪', 500, 200, '看家')
alex = Person('陈叔', 999, 111, '男')
print(jin.kind)
print(alex.sex)

super()一般都是在类内部使用,如果super要在类外部使用该如何做呢?
Super在类外部使用的时候, super(类名,对象名).(方法)使用

组合和继承的区别:

组合是 “有”的关系
继承是 “是”的关系
多继承(找大爹)
钻石继承

class A:
    def func(self):
        print('A')


class B(A):
    def func(self):
        print('B')


class C(A):
    def func(self):
        print('C')


class D(B, C):
    def func(self):
        print('D')


d = D()
print(D.mro())

在这里插入图片描述

在这里插入图片描述
mro()方法可以将继承顺序列出来
在这里插入图片描述
在这里插入图片描述
Super的本质不是直接找父类,而是根据调用者的节点位置广度优先顺序来判断的

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

在这里插入图片描述

小技巧:

如何在终端上运行点py文件呢?在这里插入图片描述
目前还存在一个疑问:shell和terminal有什么区别????

7 接口类和抽象类

接口类:

from abc import abstractmethod, ABCMeta


class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass


class Wechat(Payment):
    def pay(self, money):
        print("已经使用微信支付了%s元" % money)


class Ali(Payment):
    def pay(self, money):
        print("已经使用阿里支付了%s元" % money)


class Apple(Payment):
    def pay1(self, money):
        print("已经使用苹果支付了%s元" % money)


def pay(pay_obj, money):  # 接口

    pay_obj.pay(money)


wechat = Wechat()
ali = Ali()
apple = Apple()

在这里插入图片描述

上述写法是一种规范:当某个类中没有pay方法时,就会在实例化的时候报错
接口类:支持多继承,但是接口类中的方法都不能实现(不能理解)
抽象类:不支持多继承,但是抽象类中的方法有一些可以实现(不能理解)
abc类是一个抽象类
接口类也存在多继承
接口类和抽象类都不能实例化
在这里插入图片描述
java中没有多继承,但是为了实现多继承,可以用interface(接口)来实现

7 面向对象三大特性之多态

多态指的是一类事物有多种形态

from abc import abstractmethod, ABCMeta


class Animal(metaclass=ABCMeta): #同一类事物:动物
    @abstractmethod
    def talk(self):
        pass


class People(Animal): #动物的形态之一:人
    def talk(self):
        print('say hello')


class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print('say wangwang')


class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print('say aoao')


peo = People()
dog = Dog()
pig = Pig()

#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()

#更进一步,我们可以定义一个统一的接口来使用


def func(obj):
    obj.talk()

    
func(pig)

在这里插入图片描述

鸭子类型

Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子。
python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象
也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度(类之间的相关程度)。

关于多态的深入理解:

class Animal(object):
    def run(self):
        print('Animal is running...')


class Dog(Animal):
    def run(self):
        print('Dog is running1...')

    def eat(self):
        print('Eating meat...')


class Cat(Animal):
    def run(self):
        print('Cat is running2...')

    def eat(self):
        print('Eating meat...')


dog = Dog()
dog.run()

cat = Cat()
cat.run()
a = list()  # a是list类型
b = Animal()  # b是Animal类型
c = Dog()   # c是Dog类型


def run_twice(animal):
    animal.run()
    animal.run()


run_twice(cat)


class Tortoise(Animal):
    def run(self):
        print('Tortoise is running slowly...')


run_twice(Tortoise())

在这里插入图片描述
你会发现,新增一个Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。
多态的好处就是,当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思:
对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:
对扩展开放:允许新增Animal子类;
对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

8 面向对象三大特性之封装

class Person:
    __key = 123  # 私有的静态属性

    def __init__(self, name, password):
        self.name = name
        self.__password = password  # 私有属性

    def __get_password(self):
        return self.__password

    def login(self):
        self.__get_password()  # 私有方法


alex = Person('水月雨', 'blessing2')
print(alex.name)
print(alex._Person__password)

在这里插入图片描述
加上双__就会变成私有的,在类外部不能调用

class Room:
    def __init__(self, name, length, width):
        self.__name = name
        self.__length = length
        self.__width = width

    def area(self):
        return self.__length * self.__width

    def get_name(self):
        return self.__name

    def set_name(self, newname):
        if type(newname) is str and newname.isdigit() == False:
            self.__name = newname


jin = Room('陈叔', 10, 7)
print(jin.area())
jin.set_name('lux')
print(jin.get_name())

在这里插入图片描述
经过测试:父类中的私有属性(私有方法)在子类中也不能调用
所以能用到私有(封装)的场景有:
0)隐藏一个属性,不想在外部被调用
1)想要保护一个属性,不想让这个属性被随意改变
2)想保护这个属性,不被子类继承

在类中修改私有属性:

class People:
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name + 'sb'

    @name.setter
    def name(self, newname):
        self.__name = newname


tiger = People('泰哥')
print(tiger.name)
tiger.name = '全班'
print(tiger.name)

在这里插入图片描述

在类中删除私有属性:

class People:
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.deleter
    def name(self):
        print('我爱你')
        del self.__name


tiger = People('泰哥')
print(tiger.name)
del tiger.name
print(tiger.name)

在这里插入图片描述

9 类方法

class Goods:
    __discount = 0.8

    def __init__(self, name, price):
        self.name = name
        self.__price = price

    @property
    def price(self):
        return self.__price * Goods.__discount

    @classmethod  # 把一个方法变成一个类的方法,这个方法就可以直接被类调用,  不需要任何依托
    def change_discount(cls, newdiscount):
        cls.__discount = newdiscount


apple = Goods('苹果', 5)
print(apple.price)
Goods.change_discount(0.5)
print(apple.price)

在这里插入图片描述

10 静态方法

如果一个函数既和类没有关系,也和对象没有关系,就用staticmethod伪装成静态方法

class Login:
    def __init__(self, name, password):
        self.name = name
        self.pwd = password
        print('这把点了')

    def login(self):
        pass

    @staticmethod
    def get_info():
        user = input('请输入用户名:')
        pwd = input('请输入密码:')
        Login(user, pwd)


Login.get_info()

在这里插入图片描述
关于类方法和静态方法的总结:
类方法和静态方法,都是通过类调用的
对象也可以调用类方法和静态方法,不过推荐通过类来调用
类方法有一个默认参数 cls 代表这个类
静态方法没有默认参数, 就和普通函数一样

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页