zoukankan      html  css  js  c++  java
  • Python易错点3

     35. 多个装饰器装饰一个函数

    多个装饰器装饰一个函数时,执行时的顺序是:最先装饰的装饰器,最后一个执行。它遵循了先进后出这样一个规则

    https://www.cnblogs.com/GumpYan/p/12290166.html

    def set_fun1(func):
        print("set_fun1已被定义")    # 打印用于验证在多个装饰器的情况下,多个装饰器之间的执行顺序
        def call_fun1(*args, **kwargs):
            print("call_fun1执行了")   # 当被装饰函数执行时,会打印
            return func()
        return call_fun1
     
     
    def set_fun2(func):
        print("set_fun2已被定义")
        def call_fun2(*args, **kwargs):
            print("call_fun2执行了")
            return func()
        return call_fun2
     
    @set_fun2
    @set_fun1
    def test():
        pass
    

      运行结果:

     运行过程:

    1.修饰器本质上是一个函数,只不过它的传入参数同样是一个函数。因此依次加了set_fun1和set_fun2两个装饰器的原函数test()实际上相当于set_fun2(set_fun1(test))

    2.下面进入这个复合函数。首先执行内层函数set_fun(test),因此第一个打印的是set_fun1已被定义,接下来要注意,在set_fun1中定义了一个call_fun函数,但是没有调用它的语句,即没有set_fun1()语句。因此该函数内的语句并没有立即执行,而是作为了返回值。

    因此set_fun1内的语句都被作为输入参数传递到set_fun2内。

    3.下一步执行set_fun2()函数内容,先打印出了set_fun2已被定义,返回值为call_fun2。由于更外层没有装饰器,因此接下来就将执行call_fun2中的内容,打印call_fun2执行了,接着执行func()函数,此时func()表示的set_fun1中的内容,即有set_fun1()语句了,因此跳到set_fun1中执行,打印call_fun1执行了

     https://blog.csdn.net/yyb19951015/article/details/83014969

    比较下面的这个例子:和上面的区别

    """
    如果装饰器是多层的,谁距离函数最近,就优先使用那个
    """
    
    
    def decorate1(func):
        print("--------> 1 start")
    
        def wrapper(*args, **kwargs):
            func()
            print("刷漆")
        print("---------> 1 end")
    
        return wrapper
    
    
    def decorate2(func):
        print("--------> 2 start")
    
        def wrapper(*args, **kwargs):
            func()
            print("铺地板")
    
        print("------------> 2 end")
    
        return wrapper
    
    
    @decorate2
    @decorate1
    def house():
        print("我是毛坯房")
    
    
    house()
    

      

    36. unittest模块的使用,类的各个函数的调用顺序

    unittest是python内置的单元测试框架,具备编写用例、组织用例、执行用例、输出报告等自动化框架的条件。
    unittest工作流程:编写TestCase,由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,最后将运行的结果保存在TextTestResult中。
    testCase执行顺序:setUpClass() -> setUp() -> test1() -> tearDown() -> setUp() -> test2() -> tearDown() ->…-> tearDownClass

    37.Decimal和Round

    37.1 decimal的quantitize

    默认参数ROUND_HALF_EVEN

    看小数点最后一位

    1、大于5,直接进位

    decimal.Decimal(‘3.146’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.15’)
    decimal.Decimal(‘3.136’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.14’)

    2、小于5,直接舍去
    decimal.Decimal(‘3.143’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.14’)
    decimal.Decimal(‘3.133’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.13’)

    3、等于5,看奇偶(奇进,偶舍)

    decimal.Decimal(‘3.155’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.16’)
    decimal.Decimal(‘3.125’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.12’)
    decimal.Decimal(‘3.165’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.16’)
    decimal.Decimal(‘3.175’).quantize(decimal.Decimal(‘0.00’))
    Decimal(‘3.18’)

    37.2  Round精确存储,奇进偶舍

    奇进偶舍:

    例如数 a.bcd,我们需要保留 2 位小数的话,要看小数点后第三位

    如果 d<5,直接舍去

    如果 d>5,直接进位

    如果 d == 5:

    d 后面还有非 0 数字,例如 a.bcdef,f 非 0,那么要进位

    d 后面没有数据,且 c 为偶数,那么不进位

    d 后面没有数据,且 c 为奇数,那么要进位

    # https://www.tr0y.wang/2019/04/08/Python%E5%9B%9B%E8%88%8D%E4%BA%94%E5%85%A5/
    print(round(1.115, 2)) #1.11 #十进制小数转二进制时精度丢失的问题
    print(round(0.375, 2))  #0.38 #奇进偶舍

    from decimal import Decimal # decimal 是 Python 专门处理高精度的库
    print(Decimal(1.115))  #1.1149999999999999911182158029987476766109466552734375
    print(round(0.375, 2))  #0.38

    # 精确存储,奇进偶舍

    round(0.125, 2)

    0.12

    round(0.135, 2)

    0.14

    round(0.375, 2)

    0.38

    # 非精确表示,精度截断,实际存储值要小

    round(1.115, 2)

    1.11

    round(2.675, 2)

    2.67

    如何判断是否是精确表示,貌似只能使用decimal打印输出一下了

    from decimal import Decimal # decimal 是 Python 专门处理高精度的库
    print(Decimal(1.115))  #1.1149999999999999911182158029987476766109466552734375

    # Python3 - 执行精确的浮点数运算
    # 总的来说, decimal 模块主要用在涉及到金融的领域。 在这类程序中,哪怕是一点小小的误差在计算过程中蔓延都是不允许的
    a = 2.1
    b = 4.2
    c = a + b
    print(c)
    print(c == 6.3)
    
    # 6.300000000000001
    # False
    
    
    from decimal import Decimal
    
    a = Decimal('2.1')
    b = Decimal('4.2')
    c = a + b
    print(c)
    print(c == Decimal('6.3'))
    
    # 6.3
    # True
    
    nums = [1.23e+18, 1, -1.23e+18]
    print(sum(nums))
    # 0.0
    
    import math
    nums = [1.23e+18, 1, -1.23e+18]
    
    print(1.23e+5)
    # 123000.0
    print(math.fsum(nums))
    # 1.0
    

      

    import  decimal
    
    # 需要精确数值计算的场景,应使用decimal模块,且不要用浮点数构造Decimal
    from decimal import Decimal
    print('%.20f' % 3.14) # 输出3.14000000000000012434
    print(Decimal('3.14')) # 精确的始终只用两位小数表示
    
    
    decimal.getcontext().rounding=decimal.ROUND_HALF_UP  #4舍5入  ROUND_HALF_DOWN 不入
    c1=decimal.Decimal('2.135').quantize(decimal.Decimal('0.00'))
    print(c1) 
    

      运行结果:2.14

    c2=decimal.Decimal('2.145').quantize(decimal.Decimal('0.00'))
    print(c2)
    

      运行结果:2.14

    38. Python中的下划线变量

    (1)_xxx "单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量
    需通过类提供的接口进行访问;不能用’from module import *'导入
    (2)__xxx 类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。),
    " 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据
    (3)__xxx__ 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__()代表类的初始化函数。

     https://www.cnblogs.com/GumpYan/p/12381705.html

    39. 集合的一些操作

    39.1

    • 交集{5}

      print({1, 2, 3, 4, 5} & {5, 6})

    • 并集{1, 2, 3, 4, 5, 6}

      print({1, 2, 3, 4, 5} | {5, 6})

    • 差集{1, 2, 3, 4}

       print({1, 2, 3, 4, 5} - {5, 6})

    • 对称差分:两个集合的非共同元素{1, 2, 3, 4, 6} (set(a)-set(b))|(set(b)-set(a))

      print({1, 2, 3, 4, 5} ^ {5, 6})

    • and、or代表逻辑运算符
      • and返回第一个False的值,如果没有False的值则返回最后一项的值

        print({1, 2, 3, 4, 5} and {5, 6}) # {5, 6}

      • or返回第一个True的值,如果没有True的值则返回最后一项的值

        print({1, 2, 3, 4, 5} or {5, 6}) # {1, 2, 3, 4, 5}

    异或在数学上就是对称差(Symmetric difference)

    数学上,两个集合的对称差(Symmetric difference)是只属于其中一个集合,而不被两个集合同时包含。 例如:集合{1,2,3}和{3,4}的对称差为{1,2,4}。集合论中的这个运算相当于布尔逻辑中的异或运算。所以在Python里使用了异或的符号(^)表示,内置函数为symmetric_difference()

    39.2 集合增删

    1.添加元素add和update

    # 1.添加元素
    thisset = set(("Google", "Runoob", "Taobao"))
    thisset.add("Facebook")
    print(thisset)
    
    # 还有一个方法,也可以添加元素,且参数可以是列表,元组,字典等,语法格式如下:
    thisset.update({1, 3})
    thisset.update([1, 4], [5, 6])
    thisset.update({'a': 'aaa'})
    print(thisset)
    

      

    2.移除元素
    # s.remove( x )
    # 将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误。

    thisset = set(("Google", "Runoob", "Taobao"))
    thisset.remove("Taobao")
    print(thisset)
    # {'Google', 'Runoob'}
    # thisset.remove("Facebook")   # 不存在会发生错误
    # Traceback (most recent call last):
    #   File "<stdin>", line 1, in <module>
    # KeyError: 'Facebook'
    

    # 此外还有一个方法也是移除集合中的元素,且如果元素不存在,不会发生错误。格式如下所示:
    # s.discard( x )

    thisset = set(("Google", "Runoob", "Taobao"))
    thisset.discard("Facebook")  # 不存在不会发生错误
    print(thisset)
    
    

      运行结果:

    {'Taobao', 'Google', 'Runoob'}

    40. 元类

    class A:
        pass
    print(type(1))  # <class 'int'>
    print(type(type(1)))  # <class 'type'>
    print(type(int))  # <class 'type'>
    print(type(A))  # <class 'type'>

    • 元类是类的类,常可以用在类工厂中;
    • Python中所有的类都是对象,可以通过type( )来创建元类
    • 在定义类时,可用过metaclass参数来指定此类的元类
    • Python类语句执行时,会先查找其类本身的metaclass属性,如果没找到,会继续在父类中找,还没找到,则到模块中找,最后再用内置的type来创建此类对象
    • 使用类、函数都可以当做元类,通常在__new__()方法中通过type来自定义自己的元类
    • 从设计的复杂度来讲,尽量少用元类,多用普通类或函数

    41. 字符串拼接时间对比

    42. Python 实例方法、类方法和静态方法

    https://blog.csdn.net/lihao21/article/details/79762681

    43. [lambda x: x*i for i in range(4)] LEGB规则

    首先看

     再看:

    fun = [lambda x: x*i for i in range(4)]
    for item in fun:
        print(item(1))

    输出结果:3, 3, 3, 3

    https://blog.csdn.net/qdPython/article/details/107938206?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242

     这个问题涉及到了Python的闭包及延时绑定的知识(Python作用域)

    在Python核心编程里,闭包的定义如下:

    如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认定是闭包。

    总结为三点:

    1、是一个内嵌函数

    2、对外部函数变量引用

    3、外部函数返回内嵌函数

     简单的闭包例子:

    def counter(start_at=0):
        count = [start_at]
        def incr():
            count[0] += 1
            return count[0]
        return incr
    

     上面的那道题,可以写成这样:

    def func():
        fun_list = []
        for i in range(4):
            def foo(x):
                return x*i
            fun_list.append(foo)
        return fun_list
    for m in func():
      print m(2)
    

      m表示的是foo函数

    当我们执行 m(2) 时,运行到foo()内部函数,发现变量 i 并不是foo()中的变量,于是就到外部函数func中寻找变量 i ,但此时外部的 for 已经循环完毕,最后的 i =3 。所以,每次执行m(2),i 的值都是 3 ,因此,最终结果会是 [6, 6, 6, 6] 。

    我们打印i的值就知道了:

    def func():
        fun_list = []
        for i in range(4):
            def foo(x):
                print("i的值:", i)
                return x*i
            fun_list.append(foo)
        return fun_list
    
    for m in func():
        print(m(2))
    

      

     当在foo()中添加 i=i 后,即:

    def func():
        fun_list = []
        for i in range(4):
            def foo(x, i=i):
                return x*i
            fun_list.append(foo)
        return fun_list
    for m in func():
      print m(2)

    这样的话,for循环执行时,就已经把 i(0, 1, 2, 3) 的值传给了foo()函数,此时的 i 已经是foo()函数的内部变量,运行到foo()函数时,就不会到外部函数寻找变量 i ,直接运行

    x*i(0, 1, 2, 3),因此最终结果会是 [0, 2, 4, 6] 。

     

    44. python中的__del__方法

    https://www.cnblogs.com/GumpYan/p/12369633.html

    什么时机触发__del__()方法?

    python解释器回收所有在这一次执行过程开辟的空间,只要没有引用了,一回收就会调用__del__()方法,即当一块空间没有任何引用了,就会默认执行__del__

    python中对象的赋值就是地址的赋值

    class Person:
        def __init__(self, name):
            self.name = name
     
     
    p = Person('Jack')
    p1 = p  # 将p的地址给了p1
    p2 = p

    class Dog:
        def __del__(self):   #当内存不需要的时候调用这个删除方法,python解释器自动调用
            print(“英雄over”)
     
    dog1=Dog()  #创建一个对象
    dog2=dog1
     
    del dog1
    del dog2
    print(“==========”)
    

     输出为: 

     

     删除对象的意思就是这个对象所对应的内存空间被释放了,当dog1被删除了,dog2还在,引用计数减掉1而已,内存还不会被释放,当del dog2,内存空间的引用都被删了,就会调用__del__()方法

    class Dog:
        def __del__(self):   #当内存不需要的时候调用这个删除方法,python解释器自动调用
            print(“英雄over”)
     
    dog1=Dog()  #创建一个对象
    dog2=dog1
     
    del dog1
    print(“==========”)
    

     当删除了dog1,内存空间还没有结束,还不会调用__del__方法,当调用完最后一条语句时,内存空间被释放,调用__del__方法

     

  • 相关阅读:
    java基础1
    display:inline
    运用<ul><li>做导航栏
    ul和li 基本用法分析(这里主要想学习怎么用在导航栏中)
    转换(旋转)transform
    典型相关分析
    相关性模型-相关系数
    拟合算法
    插值算法
    评估类模型之优劣解距离法Topsis模型
  • 原文地址:https://www.cnblogs.com/GumpYan/p/14150509.html
Copyright © 2011-2022 走看看