Python入门阶段发现的一些小技巧

Python入门阶段发现的一些小技巧

  1. 对于需要循环遍历,仅仅只需要次数而不需要下标或者具体的值情况下:
for _ in  range(10)
  1. 避免循环和内存的方法就是最好输入后就解决,不要再次调用与保存
    其实这些都没必要学习,无论用什么方法,先能写出来才是王道,效率都差不太多,我还没有到那个境界。。。。。
  2. 巧妙的输入
t = int(stdin.readline())
for n in[*map(int,open(0))][1:]:
 if n%2:
     m=n//2
     d=m%2+1
     r=m-d,m+d,1
 else:r=2,n-3,1
 print(*r)

对于构造的题目(constructive)如果是判断归谬的需要多想想正反两面的问题,因为一开始的想法总是不全面的
最大公约数为1的问题

  • 偶数与奇数之间最大公约数为1
  • 相邻两个数之间最大公约数为1
  • 相邻的奇数最大公约数为1
[comment]: math库里有求最大公约数的函数:
from math import gcd as bltin_gcd
def p(a,b):
    return bltin_gcd(a,b)==1#由于是寻找一定会有GCD为1的两个数的,因为没有限制n的大小
  1. python中整除以及舍入
2//3=0
-1//2=-1#整除时会向小值舍入
round(-2.8)=-3#四舍五入同样的进位操作
  1. 经过对比可知python自带的input输入没有sys.stdin.readline().strip()要快,差距大致有100多毫秒,可以使用这种方法来替代:

    import sys
    def input():
      return sys.stdin.readline().strip()
    
  1. python中判断一个数是否是整数

    def judge(num):
      if num==round(num):
        return True
      return False
    
    #应该还用别的方法需要对比测试一套最快的算法
    
  2. 来自一个菜鸡的叙述,不要怕超时或者算法很SB,没思路就跳走,你当前的能力不足以征服此题,哎用python刷codeforce又又又超时了 😭

  3. python中的切片操作!!!!![详解][ https://zhuanlan.zhihu.com/p/79541418#:~:text=什么是切片操作 在Python中, 切片 (slice) 是对序列型对象 (如 list%2C ,string%2C%20tuple%29%E7%9A%84%E4%B8%80%E7%A7%8D%E9%AB%98%E7%BA%A7%E7%B4%A2%E5%BC%95%E6%96%B9%E6%B3%95%E3%80%82%20%E6%99%AE%E9%80%9A%E7%B4%A2%E5%BC%95%E5%8F%AA%E5%8F%96%E5%87%BA%E5%BA%8F%E5%88%97%E4%B8%AD%20%E4%B8%80%E4%B8%AA%E4%B8%8B%E6%A0%87%20%E5%AF%B9%E5%BA%94%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E8%80%8C%E5%88%87%E7%89%87%E5%8F%96%E5%87%BA%E5%BA%8F%E5%88%97%E4%B8%AD%20%E4%B8%80%E4%B8%AA%E8%8C%83%E5%9B%B4%20%E5%AF%B9%E5%BA%94%E7%9A%84%E5%85%83%E7%B4%A0%EF%BC%8C%E8%BF%99%E9%87%8C%E7%9A%84%E8%8C%83%E5%9B%B4%E4%B8%8D%E6%98%AF%E7%8B%AD%E4%B9%89%E4%B8%8A%E7%9A%84%E8%BF%9E%E7%BB%AD%E7%89%87%E6%AE%B5%E3%80%82]

    #1.切片形式形如
    a=[0,1,2,3,4,5,6,7,8,9]
    a[start:stop]----->注意这里表示的是一个前闭后闭开的切片操作
    a[2:3]------->[2]
    #注意当切片的区间超过索引的有效值时,并不会报错,会根据是否所表达的操作趋势进行截断操作
    a[100,-1]--------->0
    a[-100,5]---------->[0,1,2,3,4]
    #如果start的位置比stop还靠后怎么办?Python还是不会抛出异常,而是直接返回空序列:
    #2.缺省形式的切片操作
    a[:100]----------->[0,1,2,3,4,5,6,7,8,9]默认缺省的情况下 start无穷小,stop无穷大
    #3.带step的切片操作a[start:stop:step]
    当step为正整数的情况下:
    a[1:6:2]----------->[1:3:5]注意stop对应的值仍然是限定的值
    但step为负数的情况下:不缺省的索引与上述的索引一致,缺省的情况下,注意是反方向使得索引切片的范围最大
    a[2::-1]----------->[2,1,0]
    a[::-1]------------->[9,8,7,6,5,4,3,2,1,0]
    
  4. 解决超时问题的笨方法

    • 对于经常需要访问到的数据先初始化,相当于制造出reference表,不用每次都要初始化该表
    • 第二种笨方法就是一定要使用break,避免无用的循环操作,
    • 可以使用上面我所说的自定义input等函数
    • 如果还不行尽量尝试使用就是算法问题,有时候不是暴力求解而是找规律的
  5. python的开立方有问题

    print(1000**(1/3))#这个结果应该是10的,可是却得到了9.9999998
    

    解决办法有使用numpy库中的函数

    但是竞赛不能使用非自带库,搜了全网没有找到合适的,可以在math.floor(num)后在此加1判断一下,我目前只能想到这种方法

  6. int与math.floor的区别:数值上人类看起来差不多,但是int会改变数据的类型,而floor知识保留整数部分,数的类型没有改变

  7. 我人傻了,既是平方数又是立方数那么这个数也一定是6(2与3的最小公倍数)次方数

  8. 不要把问题东边一榔头,右边一榔头的想问题,说了不要怕超时,你TM用python还怕超时,那不是搞笑来吗,注意抓住问题的本质,比如整除的问题就不用思考别的,不要去拼凑答案,有时解题的思路都在题目里,按照题目要求去做,保准没错

  9. 冒泡排序你还会写吗?

    # 冒泡排序
    from sys import stdin
    
    
    def input():
        return stdin.readline().strip()
    
    
    data = list(map(int, input().split()))
    for i in range(len(data)):  # control times of iteration
        # becasuse of adjacent elements compare will increment itself proposingly
        for j in range(0, len(data)-i-1):
            if data[j] > data[j+1]:
                data[j], data[j+1] = data[j+1], data[j]
    
    
    print(" ".join((list(map(str, data)))))
    
  10. python中排序解析:

    1.列表中自带的sort函数

    a[4,3,2,1]
    a.sort()
    

    该方法有以下特点:原地排序,无返回值(返回值为NONE)

    ​ 拓展

    • 自定义比较方法python3取消了。。。。。但是 \(cmp_to_key\)函数可以将老式的比较函数转化为 key 函数
    #寻找m中元素所组成数值的最大值
    import functools
    m=[4,3,2,1]
    m.sort(key=functools.cmp_to_key(lambda x,y:int(str(y)+str(x))-int(str(x)+str(y))))#注意是为正执行交换的策略
    print("".join([str(i) for i in m]))
    
    • 自定义键函数(key=function())
    #比较列表m中的元素距离2的大小
    m=[4,3,2,1]
    l=sorted(m,key=lambda x:abs(x-2))
    print(l)
    

    ​ 键函数与比较函数的区别:

    1. 键函数是通过将比较对象通过该函数替换得到新值,在通过新值进行默认大小的\(cmp\)得到两个元素间的大小关系(而且key只支持一个参数不要)

    2. 比较函数则是通过比较两个元素,通过返回值来判断是否要执行交换策略,如果返回值为正数那么就执行交换策略(比较函数支持两个参数)由于目前的python版本不支持\(cmp\)函数了,我们可以通过\(functools\)中的\(cmp_to_key\)来实现,最方便的是写一个lambda函数来执行

    • 排序的reverse功能当reverse为True的时候说明执行倒序(从大到小)

    1.内建sorted()函数

    ​ 可以对可迭代对象进行排序,非原地,返回值是一个列表

    ​ 有以下特点:

    - 对于字符串会list化后按照ASCII码进行比较
    - 对于dict如果没有使用items方法,那么只是对key值进行默认排序,返回的也是key值的不带value
    - 其他功能与sort()差不多,参考上面所述

  11. 利用python自带的operator库实现更多功能

    operator模块自带运算的映射功能,包含了 许多+-*/的映射函数,下面重点介绍其中的三个类:

    • attrgettter
    • itemgetter
    • methocaller
    1. attrgetter:

    返回从其操作数所获取的attr可调用对象,如果请求多个属性,则返回属性元组,常用与不支持原生比较的对象

    1. itemgetter

    返回一个可调用对象,该操作对象使用操作数的__getitem__()方法从其操作数中获取项,如果制定了多个项,则返回一个查找元组------->就是获取指定域中的对象,所指定的元素一定是可以被下标索引的(经过不知名人士的测试,itemgetter(),比自定义的匿名函数大数据量下更高效点。。。。)

    from operator import itemgetter, attrgetter
    a = [1, 0, 8, 6, 3]
    b = {1: 4, 2: 8, 3: 4, 8: 2}
    # print(b.items())
    #保留下标索引对a进行排序
    print(sorted(enumerate(a), key=lambda x: x[1]))
    print(sorted(enumerate(a),key=itemgetter(1)))
    #对字典b进行排序根据对应的value
    print(dict(sorted(b.items(),key=lambda x: x[1])))
    print(dict(sorted(b.items(),key=itemgetter(1))))
    
    1. methocaller

    方法调用器感觉用处不大,主要是对于某些方法的调用不需要实例化,直接通过方法调用器指定参数即可使用,也可以创建operator.methocaller(arg1,arg2,arg3)生成调用对象来使用

  12. 利用python自带的functools模块

    模块适用于所有可调用对象

    1. partial:偏函数实现函数功能的动态添加与修改:( partial() 是被用作 “冻结” 某些函数的参数或者关键字参数,同时会生成一个带有新标签的对象(即返回一个新的函数)。 )
    from functools import partial
    #八进制转换为十进制
    O2D=partial(int,base=8)
    print(O2D('10'))
    
    1. update_wrapper

    2. wraps

    3. reduce:执行归约操作会将上一次迭代后的参数作为输入之一,继续执行下去

    from functools import reduce
    a='helloworld'
    b=[1,2,3,4]
    #执行字符串反转
    print(reduce(lambda x,y:y+x,a))
    #执行列表数之和
    print(reduce(lambda x,y:x+y,b))
    
    1. cmp_to_key:见上文
    2. lru_cache
    3. singledispatch
  13. 分支判断会降低你的代码执行效率,尽量减少判断,加快代码的执行效率

  14. 判断一个数是否是偶数可以通过:

a=5
if 1-(a&1):
  print("偶数")
else:
	print('奇数')
  1. 主要python中的参数传递是引用赋值,还是值拷贝,如果参数类型是mutable(list等可变类型)那么就是引用赋值,会随着改变而改变,如果参数类型是不可变的(字符串,元组)那么就是值传递,不会随着改变而改变

    • ps解决list调用参数改变,可以通过深拷贝

      import copy
      a=[1,2,3,4]
      b=a#这是引用赋值,可以说是浅拷贝
      b=copy(a)#这是引用赋值,可以说是浅拷贝
      b=copy.deepcopy(a)#这是深拷贝不会随着改变而改变
      
  2. 有时候题目给你的条件都是有用的比如说 Absent Remainder这题目中就给了你一些比较奇怪的限制比如说一定能够保证有解,而且解的数目会是math.floor(len(num)//2),这就很奇怪了,如果按照题目中的叙述,进行比较的话,那么一定会超时的,因为你需要遍历比较,其实这题不需要进行比较因为,在一个sequence中(递减的)利用余数一定被除数小就能直接写出答案不需要遍历,注意啊这些技巧的分析! 、

  3. 复习期末考试的时候发现的一个有趣的函数,chr(unicode of char ) ord(specific char),由字符ASCII进行快速的转换操作!

  4. zip函数将可迭代对象作为参数,将对象中对应的元素打包成为一个元组,然后返回zip迭代对象

    #通过zip函数可以解决list列表对获取指定行数据简单,指定列数据难的问题
    a=[[1,2,3],[4,5,6]]
    row1_data=a[1-1]
    col1_data=list([*zip(*a)][1-1])#利用zip的对应关系解决该问题
    
  5. python中使用set去重后,如何恢复原有的顺序:

    a=[1,2,3,1,2,2]
    b=list(set(a))
    b.sort(a.index)
    
  6. python列表生成式以及匿名函数里的条件判断怎么用

    a=[1,2,3,4]
    b=[i**i for i in a if i%2==0]
    c=[i*i if i%2!=0 else i+1 for i in a ]
    d=list(map(lambda x : x**2 if x %2!=0 else x,a))
    

    ps:单独一个条件(不带else)写在循环的后面,否则写在for循环的前面,if 前面表示条件成立执行的语句,else的与正常情况下一致

  7. python实现sum的自定义功能可以使用functools里的reduce功能来实现

  8. python中的字符串不支持索引功能,需要转为list就可以进行索引了,进行数据输入的时候也尤其需要注意。

  9. Python 中null 与none的区别:

    null:是空 不表示具体的值(也就是无法赋值 没有内存空间的存在 相当于空指针)

    none:一种特殊的值,空值 系统会为该值的变量 开辟内存空间 可以自由的使用

posted @ 2022-10-09 22:07  余后  阅读(90)  评论(0)    收藏  举报