python的学习之路day5

Posted smelond

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python的学习之路day5相关的知识,希望对你有一定的参考价值。

大纲:

1、双层装饰器

单层装饰器

双层装饰器

原理

2、字符串的格式化

3、format字符串格式化

4、生成器

5、递归

6、模块的安装

7、json模块

8、pickle模块

9、time模块

10、datetime模块

11、logging模块

 

双层装饰器

还是老样,没有改变:

USER_INFO = {}


def check_login(func):
    def inner(*args, **kwargs):
        if USER_INFO.get("is_login", None):
            # 用get方法拿字典里面的内容,如果字典里面没有我们要拿的参数,不会报错,给他默认返回的为None
            ret = func(*args, **kwargs)
            return ret
        else:
            print("请登录")

    return inner


def check_admin(func):  # 判断是否为管理员用户
    def inner(*args, **kwargs):
        if USER_INFO.get("is_login", None):
            if USER_INFO.get("user_type", None) == 2:  # 如果用户类型等于2,表示为管理员用户
                ret = func(*args, **kwargs)
                return ret
            else:
                print("无权限查看")  # 否者无权限查看
        else:
            print("请登录")

    return inner


@check_admin
def index():  # 超级管理员可以查看
    print("index")


@check_login
def home():  # 登录可以查看
    """
    普通用户的功能
    :return:
    """
    print("home")


def login():  # 登录
    user = input("请输入用户名:")
    if user == "admin":
        USER_INFO["is_login"] = True
        USER_INFO["user_type"] = 2
    else:  # 否者如果不为admin,表示登录的用户为普通用户
        USER_INFO["is_login"] = True
        USER_INFO["is_login"] = 1


def main():
    while True:
        inp = input("1、登录;2、查看信息;3超级管理员\\n>>>")
        if inp == "1":
            login()
        elif inp == "2":
            home()
        elif inp == "3":
            index()


main()
v1

输出:

1、登录;2、查看信息;3超级管理员
>>>2
请登录
1、登录;2、查看信息;3超级管理员
>>>3
请登录
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:user
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
无权限查看
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:admin
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
index
1、登录;2、查看信息;3超级管理员
>>>
v1的输出

 

新变化:

# 从版本以一中我们可以看到很多我们的check_admin里面重复了check_login的代码(check_admin又判断登录,又判断权限),
# 如果我们又加上了超级管理员,那我们就会又写一个重复的装饰器,
# 所以我们需要用到双层装饰器,先用check_login,判断是否登录,然后用check_admin判断是否为管理员
USER_INFO = {}


def check_login(func):
    def inner(*args, **kwargs):
        if USER_INFO.get("is_login", None):
            # 用get方法拿字典里面的内容,如果字典里面没有我们要拿的参数,不会报错,给他默认返回的为None
            ret = func(*args, **kwargs)
            return ret
        else:
            print("请登录")

    return inner


def check_admin(func):  # 判断是否为管理员用户
    def inner(*args, **kwargs):
        if USER_INFO.get("user_type", None) == 2:  # 如果用户类型等于2,表示为管理员用户
            ret = func(*args, **kwargs)
            return ret
        else:
            print("无权限查看")  # 否者无权限查看

    return inner


# 为什么check_login写上面,我们从下向上看,从index()开始,
# 可以看到先用admin装饰后,比如变成了nindex这个函数,然后再用login装饰进行装饰,比如又变成了nnindex,然后python是从上向下执行,
# 所以python会执行nnindex,判断是否登录,然后在执行nindex,判断是否为管理员,如果没有登录,
# 提示登录,如果已经登录(不为管理员),提示无权限
@check_login
@check_admin
def index():  # 管理员可以查看
    """
    管理员的功能
    :return:
    """
    print("index")


@check_login
def home():  # 登录可以查看
    """
    普通用户的功能
    :return:
    """
    print("home")


def login():  # 登录
    user = input("请输入用户名:")
    if user == "admin":
        USER_INFO["is_login"] = True
        USER_INFO["user_type"] = 2
    else:  # 否者如果不为admin,表示登录的用户为普通用户
        USER_INFO["is_login"] = True
        USER_INFO["is_login"] = 1


def main():
    while True:
        inp = input("1、登录;2、查看信息;3超级管理员\\n>>>")
        if inp == "1":
            login()
        elif inp == "2":
            home()
        elif inp == "3":
            index()


main()
v2

输出:

1、登录;2、查看信息;3超级管理员
>>>2
请登录
1、登录;2、查看信息;3超级管理员
>>>3
请登录
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:user
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
无权限查看
1、登录;2、查看信息;3超级管理员
>>>1
请输入用户名:admin
1、登录;2、查看信息;3超级管理员
>>>2
home
1、登录;2、查看信息;3超级管理员
>>>3
index
1、登录;2、查看信息;3超级管理员
>>>
v2的输出

输出效果完全一样,注意看v2的注释

 

装饰器的原理(多层原理也一样):

字符串的格式化:

%[(name)] [flags] [width].[precision] typecode
# 字符串格式化
# %[(name)] [flags] [width].[precision] typecode

# 常规的格式化
string = "博客网址:www.cnblogs.com/%s,园龄:%d个月" % ("smelond", 1)
print(string)

# %[(name)]可选,用于指定的key:
string = "博客网址:www.cnblogs.com/%(name)s,园龄:%(age)d个月" % {"name": "smelond", "age": 1}  # 用字典方式
print(string)

# flags 可选,可供选择的值有(听说没卵用)
# +   右对齐:正数前加正号,负数前加负号
# -   左对齐:正数前无符号,负数前加负号
# 空格 右对齐:正数前加空格,负数前加负号
# 0   右对齐:正数前无符号,负数前加负号;用0填充空白处
string = "博客网址:www.cnblogs.com/%(name)+20s,园龄:%(age)-10d个月" % {"name": "smelond", "age": 1}  # 占有20个空格,smelond在其中,向右对齐
print(string)

# width 可选,占有宽度

# .precision 可选,小数点后保留的位数
string = "数值:%(p).2f" % {"p": 1.23656}  # 在后面加上.然后数字,代表保留几位,有四舍五入功能
print(string)

# typecode 必选
#         s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
#         r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置(面向对象内容)
#         c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
#         o,将整数转换成 八  进制表示,并将其格式化到指定位置
#         x,将整数转换成十六进制表示,并将其格式化到指定位置
string = "%c___%o___%x" % (65, 15, 15)  # 将十进制转换为其他进制(A,17,f)
print(string)

#         d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
#         e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
#         E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
#         f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
#         F,同上
string = "%d--------%f--------%e--------%E-------%.2ef" % (100000000, 1.23456, 10000000, 10000000, 10000000)
print(string)

#         g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
#         G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
string = "%g-------%g-------%G-------%G" % (10000000, 100, 10000000, 100)
print(string)

#         %,当字符串中存在格式化标志时,需要用 %%表示一个百分号
string = "name:%s %% %%%%" % "smelond"  # 如果需要输出一个%,但是前面已经有了一个占位符,那就需要输出%%才能代表一个%,否者会报错,需要输出%%,就需要%%%%
print(string)
#
# 注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
string_formating.py
博客网址:www.cnblogs.com/smelond,园龄:1个月
博客网址:www.cnblogs.com/smelond,园龄:1个月
博客网址:www.cnblogs.com/             smelond,园龄:1         个月
数值:1.24
A___17___f
100000000--------1.234560--------1.000000e+07--------1.000000E+07-------1.00e+07f
1e+07-------100-------1E+07-------100
name:smelond % %%
输出

 

format格式化:

# [[fill]align] [sign] [#] [0] [widht] [,] [.precision] [type]
# fill         【可选】空白处填充的字符
# align        【可选】对齐方式(需配合width使用)
#   < ,内容左对齐
#   > ,内容右对齐(默认)
#   =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号 + 填充物 + 数字
#   ^ ,内容居中


# sign         【可选】有无符号数字
#   +,正号加正,负号加负;
#   -,正号不变,负号加负;
#   空格 ,正号空格,负号加负;


# #             【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
# ,            【可选】为数字添加分隔符,如:1, 000, 000
# width         【可选】格式化位所占宽度
# .precision    【可选】小数位保留精度
# type          【可选】格式化类型
#   传入” 字符串类型 “的参数
#       s,格式化字符串类型数据
#       空白,未指定类型,则默认是None,同s
#   传入“ 整数类型 ”的参数
#       b,将10进制整数自动转换成2进制表示然后格式化
#       c,将10进制整数自动转换为其对应的unicode字符
#       d,十进制整数
#       o,将10进制整数自动转换成8进制表示然后格式化;
#       x,将10进制整数自动转换成16进制表示然后格式化(小写x)
#       X,将10进制整数自动转换成16进制表示然后格式化(大写X)
#   传入“ 浮点型或小数类型 ”的参数
#       e, 转换为科学计数法(小写e)表示,然后格式化;
#       E, 转换为科学计数法(大写E)表示,然后格式化;
#       f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
#       F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
#       g, 自动在e和f中切换
#       G, 自动在E和F中切换
#       % ,显示百分比(默认显示小数点后6位)

# 两个最基本的格式化
string = "asdfasgsdf__{0}__asdf__{0}__adhkg__{1}__".format(123, "smelond")
print(string)  # asdfasgsdf__123__asdf__123__adhkg__smelond__
string = "___{name:s}___{age:d}___{name:s}".format(name="smelond", age=16)
print(string)  # ___smelond___16___smelond

# 一些常用的用法
#   空白处填充*,^字符居中,20个空格,s:字符串形式{:*^20s}
#   +有符号数值,d:十进制{:+d}
#   x 直接转换为16进制
#   #如果后面输入的为x,那就转换为16进制后再前面加上0x{:#x}
string = "_____{:*^20s}_____{:+d}_____{:x}_____{:#x}".format("smelond", 123, 15, 15)
print(string)  # _____******smelond*******_____+123_____f_____0xf

string = "百分比:{:%}".format(1.2345)
print(string)  # 百分比:123.450000%
用法
# 一些常用的用法
tpl = "i am {},age {},{}".format("seven", 16, "smelond")
print(tpl)  # i am seven,age 16,smelond

tpl = "i am {},age {},{}".format(*["seven", 16, "smelond"])
print(tpl)  # i am seven,age 16,smelond,注意,如果是列表要在前面加上*

tpl = "i am {0},age {1}, really {0}".format("seven", 16)
print(tpl)  # i am seven,age 16, really seven

tpl = "i am {0},age {1}, really {0}".format(*["seven", 16])
print(tpl)  # i am seven,age 16, really seven,列表需要加上*

tpl = "i am {name}, age {age}, really {name}".format(name="smelond", age=16)
print(tpl)  # i am smelond, age 16, really smelond

tpl = "i am {name}, age {age}, really {name}".format(**{"name": "smelond", "age": 16})
print(tpl)  # i am smelond, age 16, really smelond,注意,如果是字典需要加上两个*

tpl = "i am {0[0]}, age {0[1]}, really {1[2]}".format([1, 2, 3], [11, 22, 33])
print(tpl)  # i am 1, age 2, really 33,列表里面的列表

tpl = "i am {:s}, age {:d}".format("smelond", 16)
print(tpl)  # i am smelond, age 16

tpl = "i am {name:s}, age {age:d}".format(name="smelond", age=16)
print(tpl)  # i am smelond, age 16

tpl = "i am {name:s}, age {age:d}".format(**{"name": "smelond", "age": 16})
print(tpl)  # i am smelond, age 16,字典需要加上**

tpl = "numbers:{:b},{:o},{:d},{:x},{:X},{:%}".format(15, 15, 15, 15, 15, 15.87612)
print(tpl)  # s:1111,17,15,f,F,1500.000000%

tpl = "numbers:{0:b},{0:o},{0:d},{0:x},{0:X},{0:%}".format(15)
print(tpl)  # s:1111,17,15,f,F,1500.000000%

tpl = "numbers:{num:b},{num:o},{num:d},{num:x},{num:X},{num:%}".format(num=15)
print(tpl)  # s:1111,17,15,f,F,1500.000000%
一些常用的用法

 

生成器的使用(生成器是使用函数创建的):

# 普通函数
# def func():
#     return 123
#
#
# ret = func()  # 执行函数拿结果

# 生成器
def func():
    # print("start")
    print(111)
    yield 1
    print(222)
    yield 2
    print(333)
    yield 3  # 如果在函数里面出现了yield,这个函数就称之为生成器


ret = func()
print(ret)
# for i in ret:
#     print(i)  # 输出
# 循环第一次的时候就进入func函数里面去,进入后拿走yield后面的值,所以输出1,然后循环第二次,
# 第二次进入func函数时,找到上一次结尾的位置,从结尾的位置又开始循环(往下走),所以就是输出2
# 然后第三次
r1 = ret.__next__()  # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了1
print(r1)
r2 = ret.__next__()  # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了2
print(r2)
r3 = ret.__next__()  # 进入函数找到yield,获取yield后面的数据,然后我们就拿到了3
print(r3)


# r4 = ret.__next__()
# print(r4)  # 从函数里面可以看到没有第4个yield,所以这句要报错


#输出:
111
1
222
2
333
3
生成器的使用
# 基于生成器实现range功能
def myrange(arg):  # 相当于这是一个生成器
    start = 0
    while True:
        if start > arg:
            return
        yield start
        start += 1


ret = myrange(3)
# for i in ret:
#     print(i)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
# r = ret.__next__()
# print(r)#第四次肯定报错,因为只循环3次,从0开始

输出:
0
1
2
3
基于生成器实现range功能

 

python的递归:

自己拿着windows自带的画图工具画的,将就看吧,是有点丑

 

代码贴上

# 一个递给另外一个,一个简单的原理
def d():
    r = "end"  # 将字符串end赋给r
    return r  # 返回一个变量r


def c():
    r = d()  # 拿到函数d的返回值
    return r


def b():
    r = c()  # 拿到函数c的返回值
    return r


def a():
    r = b()  # 拿到函数b的返回值
    print(r)  # 拿到结果后输出


a()  # 输出end


# 递归
# 执行第一次时的效果
def func(n):  # 现在n=1
    n += 1  # n等于2
    if n >= 4:  # 当如果n>=4的时候
        return "end"  # 遇到return直接退出,然后返回一个字符串end
    return func(n)  # 上面if如果没执行,肯定会执行这句,返回func函数,现在的n=2


r = func(1)  # 传入实参1到func函数里去慢慢执行,然后接收返回值
print(r)  #输出end
递归

用递归实现一个1*2*3*4*5*6*7:

def func(n, x):  # n=1,x=1.......n=2,x=2.......n=3,x=6
    n += 1  # n=2.......n=3.......n=4
    x *= n  #以上是关于python的学习之路day5的主要内容,如果未能解决你的问题,请参考以下文章

Python学习之路--Day5

python学习之路day5

python的学习之路day5

python 学习之路-day5

python学习之路-day5

Python 之路 Day5