资讯专栏INFORMATION COLUMN

经验拾忆(纯手工)=> Python好用深度技能工具介绍

UnixAgain / 2434人阅读

摘要:单元素元祖这是整数这才是元祖也许这两行,你们当时疑惑过,并且现在也都知道了,当然重点并不在这里。。虽然我水平很垃圾,但是我知道匿名函数有一种执行方式叫做自执行。看吧,这就是版的匿名函数自执行方法。

单元素元祖:
a = (1)    # 这是整数1
a = (1,)   # 这才是元祖
也许这两行,你们当时疑惑过,并且现在也都知道了,当然重点并不在这里。。

我无聊的时候想过,为什么单元素元祖要这样设计 -> (1,)?
不多废话,看下面代码,自己理解:
    a = (3,)
    a = (3)
    
    a = (1+2)
    a = (1+2,)
    
    a = (1+2) + (3+4)
    a = (1+2,) + (3+4,)

注:
    这是我个人原创理解的一个微不足道的知识点,但是印象却特别深刻。
    因为我反向推测出 设计者为什么会设计出这种语法。
    (当然,也许我的推测和设计者当时的想法的并不一样~~~手动滑稽)
深/浅拷贝-copy/deepcopy(皮/肉)
"""
    最开始接触深浅拷贝的时候没太大感觉,只是普通的觉得避免数据污染就够了
    后来有一次用scrapy写爬虫的时候,层次太多导致内存有些顶不住。
    后来用的 deepcopy() 来 优化  scrapy 的 meta, 虽然效果不是特别明显,但是感觉深浅拷贝很有用
"""
    1. =号,不拷贝
        =号就意味着,引用指向同一个地址空间,‘敌动我动,敌不动我不懂’ 的感觉。 LOL一句话:"连体婴儿"~~
    2. copy:也称浅拷贝
        我用最简单的话解释一下:浅拷贝就是只能拷贝最外面的一层皮,来独立开辟空间使用,再深还是共用的
        eg:
            from copy import copy
            from copy import deepcopy
            
            a = [[1,2,3],[4,5,6]]
            b = deepcopy(a)
            b[0] = 0            # 这就是最外面的一层皮
            print(b)
            print(a)
    
    3. deepcopy:顾名思义了,深拷贝
       如果你听懂我上面的话,我感觉这个就更好理解了, 浅拷贝是皮,深拷贝那就是肉了呗。
       没错,无论套了几层的序列结构,每一层都是独立开辟空间,独立指向。
            from copy import copy
            from copy import deepcopy
            
            a = [[1,2,3],[4,5,6]]
            b = deepcopy(a)
            b[0][1] = 0    # 看清楚,这回就是里面的肉了, 深拷贝:你改哪里都行,哪里都与我无关
            print(b)
            print(a)

lambda黑科技
"""lambda相当于匿名函数,可以使代码简介,但有时也会被人唾弃,但我仍然喜欢用lambda"""

1. 试想:如果你想在lambda调用多个函数,该如何写?
    lambda: (print(1),print(2))    # 最外层加个括号即可
    
2. 如果你想让这个 lambda函数直接自执行,而不是通过赋予一个函数引用再执行?
    1. 这个也是我自己瞎鼓捣出来的。
    2. 虽然我JS水平很垃圾,但是我知道JS匿名函数有一种执行方式叫做 ‘自执行’。
    3. 把上面类比一下。
    
    看吧,这就是Python版的匿名函数自执行方法。
        Python版本: (lambda a:print(a))(1)        
        JS版:       (function(){})()
lambda的虚伪替代品-operator
"""
    据说这个模块可以替代lambda, 个人理解此模块并不那么太有实用价值,理解成本也偏高,
    建议:如果不喜欢lambda或者lambda用的很少的人,可以研究一下此模块。此模块的意图还是可以的。
    我还是喜欢使用 lambda
"""
直接上个例子:(字典基于Value来排序) 
    传统lambda写法:
        In [27]: a = {"1":6, "2":5, "3":4}
        In [28]: sorted(a.items(), key=lambda a:a[1])   # 看key= 这里
        Out[28]: [("3", 4), ("2", 5), ("1", 6)]
                                
    operator写法:
        from operator import itemgetter
        
        In [25]: a = {"1":6, "2":5, "3":4}
        In [26]: sorted(a.items(), key=itemgetter(1))   # 就是key= 这里有区别
        Out[26]: [("3", 4), ("2", 5), ("1", 6)]

如果上面两种新旧方法都很模糊,那么我再解释一下: 我认为上面能让人头疼的也就是 索引 1 了!!!!
    sorted, map这种高阶函数,我之前也多带带讲过,它会把 一个序列的每一个元素用管道函数进行映射。
    
    sorted稍微特殊一点,它的管道函数方法变成了key=这里: (变相理解为 指定排序的基准/参考)
        1. key=lambda a:a[1]
            指定基准:序列a的 每子元素 的 第1号索引子元素    # eg: [[1,2],[3,4],[5,6]]  就是2,4,6
        
        2. key=itemgetter(1)
            指定基准:同上一模一样,只不过写法不一样,逻辑步骤就是 原原本本从 lambda那里演变过来的。
            
总结与个人观点:
    1. operator 模块只是 lambda 使用思想 的 高一层的封装
    2. 让使用者可以忽略lambda格式细节
    3. 但是我认为 如果lambda都用不好, 那么 这个 itemgetter(1) 这种子元素 索引的指定 也会很困难
    4. 所以我还是建议用 lambda, 当你 lambda思想练熟了之后, 用 operator看看官方文档就是很快的事情
    
            
      
            
                            
封包/拆包(解构赋值)/函数占位参数骚操作
"""
    再次说明一下:我写的所有的都是Py3的/   Py2的解构赋值可能有些出入,此处我只说Py3
"""

封包:
    1)
        def f(a,*b):
            print(a)    # 1
            print(b)    # (2,3,4)
        f(1,2,3,4)
    2) 
        def f(**kwargs):
            print(kwargs)    # {"a": 3, "b": 4}
        f(**dict(a=3,b=4))
        
拆包(解构赋值):
    """
        我说过太多次了, ES6的语法和Python很像。解构赋值这个词也是从ES6听到的。
        不过ES6的解构,还可以解构 {} 和 解构空值 和 解构默认值,   而Python不可以
    """
    1)  只要第一个
            a, *_ = range(5)
            print(a, _)     # 0  [1, 2, 3, 4]

    2)  只要第一个和最后一个
            a, *_, c = range(5)
            print(a, _, c)    # 0  [1, 2, 3]  4
            
    3)  只要最后一个
            *_, b = range(5)
            print(_, b)      # [0, 1, 2, 3]  4


函数占位参数骚操作:
    """
        这是我在源码中看到的,当时觉得很惊讶,自己试了一下,下面说下自己的理解:
        这个*的作用就是: (*后面的参数是 调用时 必须命名 且 必须传递 的参数)
            a你必须给我传过来,但是你不写   a=
            b你必须给我传过来,但是你必须写 b=
    """
    def f(a,*,b):
        print(a)
        print(b)
    f(1,b=3)    # f(a=1,b=3)    # 只能通过这两种方式调用
反射-getattr & setattr & hasattr & delattr & import_module
综合例子:
    from importlib import import_module
    random = import_module("random")          # 动态反射导入模块  
    # 或 random = __import__("random")         
    if hasattr(random, "randint"):            # 检测模块中是否有函数
        randint = getattr(random,"randint")   # 动态反射导入函数
        print(eval("randint(0,1)"))               # 字符串转语句执行(类似反射)
    
getattr & setattr & hasattr & delattr 讲解:
    hasattr & getattr
        random = __import__("random")
        if hasattr(random,"randint"):    # 检测 random 模块中是否有 randint 函数
            randint = getattr(random,"randint")
            print(randint(0,1))
            
    delattr & hasattr 
        delattr(random, "randint")      # 动态删除模块中的 randint函数
        if not hasattr(random,"randint"):
            print("没有此函数了,让delattr删除了")
            
    setattr & getattr                   # 动态重新设置模块的 randint函数,并给个函数体
        setattr(random, "randint", lambda:print("设置这个方法凑合用把。"))
        randint = getattr(random, "randint")
        randint()     

模块重新导入到内存-reload
from imp import reload
import time
reload(time)
print(time.time())
进度条-tqdm
for x in tqdm(range(100)):
    import time
    time.sleep(1)
    print(x)
tqdm包装一个可迭代对象, 只是装饰了一下,使用方法还是像原来一样使用。 
票数统计-Counter
In [2]: from collections import Counter

In [3]: Counter([1,2,3,4])
Out[3]: Counter({1: 1, 2: 1, 3: 1, 4: 1})

In [4]: Counter([1,1,1,2,2,3])    # 统计频次
Out[4]: Counter({1: 3, 2: 2, 3: 1})

In [5]: Counter([1,1,1,2,2,3]).most_common(1)    # 频次最多的前1个
Out[5]: [(1, 3)]
文件 复制/移动-shutil
import shutil
shutil.copy(源,目标)    # 复制
shutil.move(源,目标)    # 移动,改名
shutil.rmtree(r"目录名")  # 删除目录(级联删除)    # 参数只能是目录
文件遍历-os.walk
"""
    os.walk() 是一个深度遍历模式的文件遍历函数
    返回值是一个迭代器,遍历这个迭代器后,每一次的返回值都是如下顺序三种构成
        1. current_path: 当前路径 
        2. dir_list:     其下目录列表
        3. file_list:    其下文件列表
    
"""
import os
file_generator = os.walk("D:/虚拟E盘-代码空间/TF2")
for current_dir, dir_list, file_list in file_generator:
    print(current_dir, dir_list, file_list)
非阻塞执行cmd/shell-subprocess
"""
    主要代替os.system
""" 
import subprocess
res = subprocess.run("dir", shell=True, stdout=subprocess.PIPE) # 结果输入到res管道中去
print(res.stdout.decode("gbk"))    # res管道中有输出日志,如果在win下,需要 decode
排列组合-itertools模块
import itertools
list(itertools.product([1,2,3],repeat=3))    # 复制3份有序全排列, repeat=3    
list(itertools.permutations([1,2,3], 3))     # 内部有序排列, 3表示最后排列为几位
list(itertools.permutations([1,2,3,4],3))    # 无序组合, 3表示3位
枚举-emunerate
In [100]: list(enumerate(list("abcde"),start=1))    # 默认从0,开始标号, start=1就从1开始
Out[100]: [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]

In [108]: list(enumerate(((1,2),(3,4))))
Out[108]: [(0, (1, 2)), (1, (3, 4))]        

In [106]: list(enumerate({"a":"c","b":"d"}))
Out[106]: [(0, "a"), (1, "b")]
global & nonlocal & globals() & locals()
global: 函数外的变量只能在函数内部取值,而不能修改, 如果想要在函数内部修改外部变量, ‘global 变量名’ 即可
    a = 1
    def f():
        global a
        a += 1
        print(a)
    f()
        
nonlocal: 原理同上一模一样,只不过应用场景是闭包了,代码如下:
    def f():
        a = 1
        def f1():
            nonlocal a
            a = a+1
            print(a)
        f1()
    f()

日历-calendar
import calendar
calendar.calendar(2019)    # 返回2019年的日历
calendar.month(2919,5)    # 返回2019年5月的日历
calendar.isleap(2000)    # 判断2000年是否为闰年
时间/日期-time/datetime
import time
1. 时间戳:
    time.time()
    
2. 字符串转时间(p-pass方便记忆)
    from datetime import datetime
    fordate = datetime.strptime("2019-5-25 9:30:30", "%Y-%m-%d %H:%M:%S")
    print(fordate)

3. 时间转字符串(f-from方便记忆)
    from datetime import datetime
    strdate = datetime.strftime(fordate, "%Y-%m-%d %H:%M:%S")
    print(strdate)
    
4. 初始化时间
    from datetime import datetime
    dt1 = datetime(2019,5,25,9,37)    # 初始化时间为 datetime格式
    dt1 = datetime.now()   # 获取当前时间为 datetime格式
    print(dt1.year)
    print(dt1.month)
    print(dt1.day)
    print(dt1.hour)
    print(dt1.minute)
    print(dt1.second)



    

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43889.html

相关文章

  • 经验拾忆手工)=> Python基本数据类型

    摘要:不要疑惑,告诉你答案这个代表正负号的正。虽然一点技术含量没有,但是你要懂序列也许叫可迭代对象更为合适,但是我喜欢叫序列。 数据结构 可变类型与不可变类型(重头戏) 基操: 可变类型:[], {} # 可增删改 查 不可变类型: int float str () # 无法增删改, 只可查 升操: + 与...

    Andrman 评论0 收藏0
  • 经验拾忆手工)=> Linux实用工具命令

    摘要:为啥直接不行呢因为以开头的最后一条命令是。和和和强制终止最常用的,先提出来。。。。我们可以通过这一条命令来迅速回到程序运行的环境。其实这些配置文件以及这些命令和用户以及权限等都是有很大关系的。 Ubuntu16升级到18.04 有特殊新颖强迫症癖好可以升下,如果你觉得16.04好用,就根本没必要升了 我当时租的 云服务器通常都是16.04,现在估计也是16.04较多 我是个...

    kk_miles 评论0 收藏0
  • 经验拾忆手工)=> Python高阶函数操作

    摘要:解释就相当于把每个序列元素的每一个单独用一个管道函数处理,再把他们按顺序组合成一个新可迭代对象注意这个管道函数只能是单参数函数,如果想传递多个参数怎么办使用偏函数怕有些人看不懂,这里就不用了,而是用普通函数定义方式固定值固定值固定值固定值固 map In [25]: list(map(lambda a:a**2, [1,2,3,4])) Out[25]: [1, 4, 9, 16] 解...

    Elle 评论0 收藏0

发表评论

0条评论

UnixAgain

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<