码迷,mamicode.com
首页 > 编程语言 > 详细

python自动化21期day7

时间:2018-05-21 23:38:38      阅读:258      评论:0      收藏:0      [点我收藏+]

标签:日志打印   json   没有   yield   student   tle   一个   option   pat   

一、面向对象

  1、封装

# 广义上的封装 :把变量和函数都放在类中
# 狭义上的封装 :把一些变量 或者 方法 隐藏起来,不对外公开
    # 公有的 :
    # 私有的 : __名字

# 静态属性 、 对象属性、 方法(动态属性) 前面加上双下划綫都会变成私有的
# 私有的特点就是只能在类的内部调用,不能在类的外部使用
# 私有的变量 :在类的内部 如果使用__变量的形式会发生变形,python会自动的为你加上_类名


class Person:
    __country = 中国    # 私有静态属性

    def __init__(self,name,pwd):
        self.name = name
        self.__pwd = pwd      # 私有的对象属性

    def login(self):
        print(self.__dict__)
        if self.name == alex and self.__pwd == alex3714:
            print(登录成功)


alex = Person(alex,alex3714)
alex.login()
print(alex.__dict__)

# 私有的名字 只能在类的内部使用 不能在类的外部使用:AttributeError: type object ‘Person‘ has no attribute ‘__country‘
print(Person.__country)

# python中不并能真正的隐藏属性,是通过变形的方式实现。_Person__country
# 如果非要在类的外部调用一个私有的名字,name必须是在私有的名字前面加 _类名__私有的名字
print(Person._Person__country)

Person.__name = XXX
print(Person.__name)   # 在类的外部不能第一一个私有变量,只有在类定义的时候__名称才叫做私有属性
技术分享图片
# 类内方法的调用过程
class Foo:
    def __init__(self):  # 第二步 找到父类的__init__ 这时候self = s 即 Son类的对象
        self.func()   # 第三步执行父类s.func()

    def func(self):
        print(in Foo)


class Son(Foo):
    def func(self):  # 第四步 执行func方法
        print(in son)


s = Son()  # 实例化类,第一步去执行__init__函数由于Son没有__init,会去父类找__init__


# 类内私有方法的调用过程
class Foo:
    def __init__(self):  # 第二步 找到父类的__init__ 这时候self = s 即 Son类的对象
        self.__func()    # 第三步 类在定义的过程中已经把私有属性变形为 self._Foo__func
                         # 第四步 执行self._Foo__func

    def __func(self):   # 类在定义的时候变形为 _Foo__func
        print(in Foo)


class Son(Foo):
    def __func(self):    # _Son__func
        print(in son)

    def start(self):
        self.__func()


s = Son()  # 实例化类,第一步去执行__init__函数由于Son没有__init,会去父类找__init__
私有属性的调用顺序问题
技术分享图片
import hashlib
# 隐藏加密方法

class MyLogin:
    def __init__(self, name, password):
        self.name = name
        self.__password = password  # 密码私有化

    def __encryption_md5(self):  # 加密方式私有化
        """
        普通md5密码
        :return: 加密后的字符串
        """
        md5obj = hashlib.md5()   # 实例化一个md5摘要算法的对象
        md5obj.update(self.__password.encode(utf-8))  # 使用md5算法的对象来操作字符串
        return md5obj.hexdigest()

    def __encryption_md5_salt(self):  # 加密方式私有化
        """
        md5加盐
        :return: 加密后的字符串
        """
        md5obj = hashlib.md5("sunpengfei".encode("utf-8"))   # 实例化一个md5摘要算法的对象
        md5obj.update(self.__password.encode(utf-8))  # 使用md5算法的对象来操作字符串
        return md5obj.hexdigest()

    def __encryption_md5_salt1(self):  # 加密方式私有化
        """
        md5动态加盐
        :return: 加密后的字符串
        """
        md5obj = hashlib.md5(self.name.encode("utf-8"))   # 实例化一个md5摘要算法的对象
        md5obj.update(self.__password.encode(utf-8))  # 使用md5算法的对象来操作字符串
        return md5obj.hexdigest()

    def login(self):
        """
        202cb962ac59075b964b07152d234b70
        5dfb835be352750bb15045eae941b8c7
        6b783000a3177ac09ae3706a077d6d80
        :return:
        """
        self.__password = self.__encryption_md5_salt1()
        if self.name == "spf" and self.__password == "202cb962ac59075b964b07152d234b70":
            return "Success"
        if self.name == "spf" and self.__password == "5dfb835be352750bb15045eae941b8c7":
            return "Success"
        if self.name == "spf" and self.__password == "6b783000a3177ac09ae3706a077d6d80":
            return "Success"


spf = MyLogin("spf", "1235")
print(spf.login())
练习题:登录增加mad5校验,用户不可以访问你的加密方式

  2、类中的装饰器方法

技术分享图片
# classmethod
# 如果某一个类中的方法 并没有用到这个类的实例中的具体属性,只是用到了类中的静态变量就使用类方法


class Person:
    Country = 中国人

    @classmethod       #把func变成了一个类方法
    def func(cls):     # cls是指向类的内存空间
        print(当前的角色的国籍是%s% cls.Country)


alex = Person()
alex.func()
Person.func()
classmethod
技术分享图片
# staticmethod
# 如果 一个方法 既不会用到对象中的属性也不会用到类中的属性就应该被定义为一个静态方法


class Student:
    @staticmethod
    def login():
        name = input(name : )
        pwd = input(pwd : )
        if name == "" and pwd == "":
            print(实例化)

# Student.login()
staticmethod
技术分享图片
# property
# 将一个函数伪装成为属性,在面向对象中动作被称为方法,但有些时候一些名词也用作方法。为了严谨可以把名词函数修改成属性


# 示例1:圆形类
# 方法 动词 —— 动作或者技能
# 名词 圆的面积 圆的周长 圆的半径
# 将一个函数伪装成为属性 @property
from math import pi
class Circle:
    def __init__(self,r):
        self.r = r

    @property
    def area(self):
        return self.r ** 2 * pi

    @property
    def perimeter(self):
        return self.r * 2 * pi



c = Circle(3)
print(c.area)
print(c.perimeter)

# 示例2:property 在__私有属性中的应用


class Goods:
    """计算商品打折后的价格"""
    def __init__(self, price, discount):
        self.__price = price  # 价格为私有属性
        self.discount = discount

    @property
    def price(self):
        """
        计算商品打折后的价格
        :return: 返回打折后的价格
        """
        return self.__price * self.discount

    @price.setter
    def price(self, newprice):
        """
        修改商品的价格
        :param newprice:
        :return:
        """
        self.__price = newprice

    @price.deleter
    def price(self):
        """
        删除商品的价格
        :return:
        """
        del self.__price


apple = Goods(8, 0.7)  # 实例化一个苹果对象
print(apple.price)
apple.price = 10    # 修改苹果的价格,私有属性无法修改。所以用到了property
print(apple.price)
print(apple.__dict__)
del apple.price
print(apple.__dict__)
print(apple.price)
property

  3、反射

# 什么叫反射?
# 通过字符串数据类型的 变量名 来访问变量的值
# x.y 这样的形式 都可以用反射
# 类名 反射 静态属性

class Foo:
    country = "中国"
obj = Foo()
print(getattr(obj, "country"))

# 对象名 反射 对象属性 和 方法
class Foo:
    country = "中国"
    def __init__(self,name):
        self.name = name
    def func(self):
        print("%s in func" %self.name)
obj = Foo("spf")
getattr(obj, "func")()


# 模块 反射 模块中的名字
import sys
from  mypickle import MyPickle
choice = input(">>>:")
getattr(MyPickle, choice)(obj, "test.pkl")


# 反射 自己所在文件中的名字
from  mypickle import MyPickle
choice = input(">>>:")
ret = getattr(sys.modules[__name__], choice)
ret.dump(obj, "test.pkl")
print(ret.load("test.pkl"))

# 首先 使用getattr取获取一个名字,如果在这个对象的命名空间中没有这个名字 会报错
# getattr的反射好伴侣 hasattr
# 如果使用getattr取获取一个方法,那么只能拿到这个方法的内存地址 加上括号就是执行,当然,括号里的参数可以照传不误
# 如果getattr获取一个属性,那么直接使用反射就可以获取到值

  4、类的内置方法

技术分享图片
# __new__    构造方法 创建一个对象
# __init__   初始化方法

class Foo:
    def __new__(cls, *args, **kwargs):
        print(执行我啦)
        obj = object.__new__(cls)
        print(obj)
        return obj
    def __init__(self):
        print(1, self)

Foo()

# 先执行new方法,object.new()
# 再执行init

# Foo()  --> python解释器接收到你的python代码
# python解释器替你去做了很多操作
# 包括 主动帮助你 调用 new方法 去创造一个对象 —— 开辟内存空间 —— python语言封装了开辟内存的工作
# object的new方法里 —— 帮你创造了对象
# 调用init用到的self参数 就是new帮你创造的对象
__new__
技术分享图片
# 什么叫单例模式
# 单例模式 : 某一类 只有一个实例

class Person:
    __isinstance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__isinstance :
            obj = object.__new__(cls)
            cls.__isinstance = obj
        return cls.__isinstance
    def __init__(self,name):
        self.name = name

alex = Person(alex)
alex.age = 18
egon = Person(egon)
print(egon.age)
print(id(alex))
print(id(egon))
print(alex.name)
print(egon.name)

# __new__生孩子
# 类 : 生一个小孩__new__ 给这个小孩穿衣服 __init__
# 单例模式下的类 : 只有一个小孩
__new__单例模式

二、模块

  1、序列化

    什么叫序列化呢?
    数据类型 —> 字符串的过程

    什么时候要用序列化呢?
    数据从内存到文件
     数据在网络上传输 字节 - 字符串 - 字典

    python中的序列化模块都有哪些?
    json 通用的 支持的数据类型 list tuple dict
    pickle python中通用的 支持几乎所有python中的数据类型
    shelve python中使用的便捷的序列化工具
技术分享图片
# json
# dumps loads
# 内存读写
import json
dic = {"k": v}
json_dic = json.dumps(dic)   # 字典转字符串的过程 ——序列化
print(json_dic)
print(json.loads(json_dic))  # 字符串转回其他数据类型 —— 反序列化

# dump load
# 文件读写
dic = {"k": v}
with open(test.json, w) as f:
    json.dump(dic, f)
    # json.dump(dic, f)       # 在json中 dump默认不支持dump多条数据

with open(test.json) as f:
    print(json.load(f))      # 从文件中反序列化


# 如果要dump多条数据,每一条数据线dumps一下 编程字符串 然后打开文件 write写进文件里 \n
# 读取的时候按照标志读取或者按行读,读出来之后 再使用loads
with open(test.json, w) as f:
    str_dic = json.dumps(dic)
    f.write(str_dic+\n)
    f.write(str_dic+\n)
    f.write(str_dic+\n)
    f.write(str_dic+\n)

with open(test.json) as f:
    for line in f:
        print(json.loads(line.strip()))
json
技术分享图片
# pickle 和 json用法一致。但是pickle可以dump多条数据
# 1.pickle支持更多的数据类型
# 2.pickle的结果是二进制
# 3.pickle在和文件交互的时候可以被多次load
import pickle


class A:
    def __init__(self,name):
        self.name = name

alex = A(alex)
print(pickle.dumps(alex))
with open(test.pkl, wb) as f:
    pickle.dump(alex, f)
    pickle.dump(alex, f)     # 可以dump多条数据
    pickle.dump(alex, f)     # 可以dump多条数据

with open(test.pkl, rb) as f:
    while True:  # 通过循环取出所有的数据
        try:
            obj = pickle.load(f)
            print(obj.name)
        except EOFError:
            break
pickle
技术分享图片
# shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
# shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。
import shelve
f = shelve.open(shelve_file)
f[key] = {int:10, float:9.5, string:Sample data}  #直接对文件句柄操作,就可以存入数据
f.close()

import shelve
f1 = shelve.open(shelve_file)
existing = f1[key]  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
f1.close()
print(existing)
shelve
技术分享图片
import pickle


class MyPickle:
    @staticmethod
    def load_iter(filename):
        """
        反序列化
        :param filename: 反序列化的文件路径
        :return: 一个存放反序列化数据的生成器
        """
        with open(filename, "rb") as f:
            while True:
                try:
                    yield pickle.load(f)
                except EOFError:
                    break

    @staticmethod
    def load(filename):
        """
        反序列化
        :param filename: 反序列化的文件路径
        :return: 一个列表,列表存储一个或者多个反序列化后的数据
        """
        result = []
        with open(filename, "rb") as f:
            while True:
                try:
                    result.append(pickle.load(f))
                except EOFError:
                    break
        return result

    @staticmethod
    def dump(obj, filename):
        """
        序列化
        :param obj: 需要进行序列化的对象
        :param filename: 序列化后文件存储路径
        :return:
        """
        with open(filename, "ab") as f:
            pickle.dump(obj, f)
练习:MyPickle

  2、hashlib

import hashlib
# hashlib特性:
# 1、单向不可逆 (采用摘要算法)
# 2、将一个字符串进行摘要运算 拿到不变的 固定长度的值
# 用途:
# 1、存储用户密码的时候 : 不