分类目录归档:解决方案

Python 30秒就能学会的漂亮短代码(译3)

1.分组

对一个列表根据所需要的大小进行细分:

from math import ceil

def chunk(lst, size):
  return list(
    map(lambda x: lst[x * size:x * size + size],
      list(range(0, int(ceil(len(lst) / size))))))

效果如下:

EXAMPLES
chunk([1, 2, 3, 4, 5], 2) # [[1,2],[3,4],5]

return中,map的第二个参数是一个列表,map会将列表中的每一个元素用于调用第一个参数的 function 函数,返回包含每次 function 函数返回值的新列表。

2.数字转数组

同样是一则关于map的应用,将整形数字拆分到数组中:

def digitize(n):
  return list(map(int, str(n)))

效果如下:

EXAMPLES
digitize(123) # [1, 2, 3]

它将整形数字n转化为字符串后,还自动对该字符串进行了序列化分割,最后将元素应用到map的第一个参数中,转化为整形后返回。

3.非递归斐波那契

还记得菲波那切数列吗,前两个数的和为第三个数的值,如0、1、1、2、3、5、8、13….

如果使用递归来实现这个数列,效率非常低下,我们使用非递归的方式实现:

def fibonacci(n):
  if n <= 0:
    return [0]

  sequence = [0, 1]
  while len(sequence) <= n:
    next_value = sequence[len(sequence) - 1] + sequence[len(sequence) - 2]
    sequence.append(next_value)

  return sequence

效果如下:

EXAMPLES
fibonacci(7) # [0, 1, 1, 2, 3, 5, 8, 13]

这样看是很简单,但是思维要绕的过来哦。

4.下划线化字符串

批量统一变量名称或者字符串格式。

from re import sub

def snake(s):
  return '_'.join(
    sub('([A-Z][a-z]+)', r' \1',
    sub('([A-Z]+)', r' \1',
    s.replace('-', ' '))).split()).lower()

效果如下:

EXAMPLES
snake('camelCase') # 'camel_case'
snake('some text') # 'some_text'
snake('some-mixed_string With spaces_underscores-and-hyphens') # 'some_mixed_string_with_spaces_underscores_and_hyphens'
snake('AllThe-small Things') # "all_the_small_things"

re.sub用于替换字符串中的匹配项。这里其实是一个“套娃”用法,一开始可能不太好理解,需要慢慢理解。

第一个替换,是将s字符串中,使用’ ‘替换’-‘。

第二个替换,是针对第一个替换后的字符串,对符合'([A-Z]+)’正则表达式的字符区段(全大写的单词)用r’ \1’替换,也就是用空格区分开每一个单词。

第三个替换,是对第二个替换后的字符串,对符合'([A-Z][a-z]+)’正则表达式的字符区段(也就是首字母大写,其他字母小写的词语)用r’ \1’替换,也是将单词用空格分隔开。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 元组Tuple 相对于数组List的优势

我们知道元组tuple是 Immutable (不可修改)的,而数组List是可变的,而且元组有的功能它都有,而且功能更多,应用更广,那为什么还要保留元组呢?

1.安全共享

假设你有几个关键词比如:CAR, AIRPLANE, BOAT. 如果它是数组,要在多个对象之间进行共享,数组无法避免它在共享的时候被无意地更改,如果说这三个关键词直接和数据中某个字段做映射,这种则更改非常危险,小则导致垃圾数据的产生,大则导致某些功能出现缺陷。

元组的好处之一就在于这里,一旦三个关键词被设定为元组,则再也无法更改。非常适合用于固定关键词在对象之间的共享。

2.性能快

我们可以做一些性能测试:

创建

>>> import timeit
>>> print(timeit.timeit('["CAR", "AIRPLANE", "BOAT"]'))
0.0508033999999995
>>> print(timeit.timeit('("CAR", "AIRPLANE", "BOAT")'))
0.013855500000001797

可以看到,元组的创建速度仅是数组的四分之一。

空间

>>> a_tuple = ("CAR", "AIRPLANE", "BOAT")
>>> b_list = ["CAR", "AIRPLANE", "BOAT"]
>>> from sys import getsizeof
>>> getsizeof(a_tuple)
72
>>> getsizeof(b_list)
88

可以看到,元组比数组少占用一些空间。

3.作为函数返回值

其实Python的函数多返回值就是用tuple实现的。我们知道tuple有两种定义方式,一种是不带括号的,一种是带括号的:

my_tuple = "CAR", "AIRPLANE", "BOAT"
my_tuple2 = ("CAR", "AIRPLANE", "BOAT")

print(type(my_tuple)) # <class 'tuple'>
print(type(my_tuple2)) # <class 'tuple'> 

而函数使用多返回值的时候是用逗号分隔开的,这是上述的元组第一种创建形式,因此,函数多返回值实际上返回的是一个元组。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 不可变对象真的不可变吗?

在日常的工作和学习中,经常会遇到“不可变对象 ” 相关的问题,但是随着接触Python这门语言的时间越来越多,遇到的坑越来越奇怪。我不禁产生了一个疑问:不可变对象真的不可变吗?

我们知道元组就是”不可变对象”,当你想尝试给一个元组赋值的时候,它会报错:

>>> my_tuple = ("python", "dict", "is", "good")
>>> my_tuple[3] = "excellent" 
Traceback (most recent call last):   
File "<stdin>", line 1, in <module> 
TypeError: 'tuple' object does not support item assignment 

请注意报错的语言: “does not support item assignment “, 元组对象不支持赋值操作。

例1

让我们来看看下面这样的操作:

>>> int_tuple = ([6,5,30], [2,3,65], [111])
>>> int_tuple[2] += [22,33]
Traceback (most recent call last):  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> int_tuple([6, 5, 30], [2, 3, 65], [111, 22, 33]) 

尽管报了一个错,但是它变量的值已经被改变了。

原因

其实,这里主要是因为 += 操作对于“不可变对象”会产生新的变量并绑定到原有变量上。但是又由于+=中的”=”号,执行了一次对元组对象的赋值操作,这是不允许的,因此报了错,但新的对象已经被绑定到了原有变量中,因此我们可以看到变量的值发生了改变。

例2

还有一种情况是这样的:

>>> int_tuple = ([6,5,30], [2,3,65], [111])
>>> int_tuple[2].append(123123)
>>> int_tuple
([6, 5, 30], [2, 3, 65], [111, 123123]) 

这里完全没有报错,为什么呢?因为append并不涉及到赋值操作,元组只是不允许赋值,并没有不允许append和extend啊,所以称元组为“不可变对象” 实在是太不严谨了!

深一点

其实如果你知道元组中存放的是元素所对应的地址(ID),就好理解多了,append和extend仅仅是修改了列表的元素,而列表本身的ID并没有发生变化,只有当赋值操作执行的时候,ID才会发生变化,而这种情况是元组不允许发生的。

# append 不会发生地址变化
>>> int_tuple = ([1], [2], [3])
>>> id(int_tuple[1])
2729947990600
>>> int_tuple[1].append(22)
>>> id(int_tuple[1])
2729947990600 

因此,要避免踩上这些坑,忘掉元组是“不可变对象”这样不严谨的表述形式(当然从地址的角度来讲它是对的,元组内部所有元素的ID都不可变),请这样记:元组是不可赋值对象

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 9行代码批量翻转壁纸的惊喜

今天在欣赏一些新的手机壁纸的时候,不小心把手机拿反了,但是却因此偶然看到了非常有特色的图片。因此突然有了推送的灵感——用Python批量翻转图片

其实原理很简单,用九行代码就能完成我们所需要的功能。

1.准备

为了能够翻转图片,我们需要先安装好PIL,也就是pillow,在CMD/Terminal输入:

pip install pillow

请记得先安装Python,才能够pip,如果你还没有安装Python,请看这篇文章: 超详细Python安装指南

2.编程

仅需要3个步骤:

1.获得图片文件夹下所有文件名

2.迭代所有图片

3.翻转保存到指定文件夹

#-*- coding: UTF-8 -*- 

from PIL import Image
import os

# 获得文件夹下所有文件
filePath = './imgs/'
filenames = os.listdir(filePath)

# 指定保存的文件夹
outputPath = './imgs_rotate/'

# 迭代所有图片
for filename in filenames:
    # 读取图像
    im = Image.open(filePath + filename)

    # 指定逆时针旋转的角度
    im_rotate = im.rotate(180)
    
    # 保存图像
    im_rotate.save(outputPath + filename) 

3.效果

嘻嘻,其实也是相当于壁纸分享了,当然,微信公众号会有压缩的现象,大家如果想下载原图请点击下方阅读原文,或者关注文章最下方Python实用宝典公众号,回复 翻转壁纸

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 小坑之字符串驻留

本文整理了许多字符串驻留的坑,部分整合自wtfpython英文版,并增加了大量的后续说明。

# example1:
>>> a = "wtf"
>>> b = "wtf"
>>> a is b
True

# example2:
>>> a = "wtf!"
>>> b = "wtf!"
>>> a is b
False

# example3:
>>> a, b = "wtf!", "wtf!"
>>> a is b 
True # 3.7 版本返回结果为 False. 
# example4:
>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
True
>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
False # 3.7 版本返回结果为 True  

字符串的这些问题,像是在和你说 1 != 1 一样坑爹。

究其原因,其实是CPython在编译的时候会自动进行优化,在某些情况下它会尝试使用已经存在的不可变对象,而不是创建一个新的对象,而恰好,字符串就是不可变对象。这种使用已存在的不可变对象的行为被称为“驻留 ” 。

驻留的原本设计意图是用于节省内存的,但是确实有时候会坑到程序员。怎样判断自己的字符串会否被驻留呢?请看这份代码:
https://github.com/python/cpython/blob/3.6/Objects/codeobject.c#L19

简单地来讲:

1.所有长度为0和1的字符串都会被驻留

2.字符串在编译时被实现的会被驻留(如’wtf’会被驻留,但是 ”.join([‘w’, ‘t’, ‘f’]) 不会)

3.字符串中只包含ASCII下的字母、数字和下划线时会被驻留. 所以’wtf!’由于包含!不会被驻留。

我们的example1中,由于发生了驻留,所以a和b是同一个字符串对象。而example2中,由于没有发生字符串驻留,a=”wtf!”和b=”wtf!”实际上使用的不是同一个字符串对象,你可以使用id获得对象的唯一标志,你会发现它们的不同:

a和b都为wtf!时:

>>> a = "wtf!"
>>> b = "wtf!"
>>> a is b
False
>>> a == b
True
>>> id(a)
2272774097864
>>> id(b)
2272774097024  

再来看看没有发生驻留时的情况,a和b都为wtf时:

# a和b都为wtf
>>> a = "wtf"
>>> b = "wtf"
>>> a is b
True
>>> a == b
True
>>> id(a)
2272774096744
>>> id(b)
2272774096744 

明白了吧?如果你想从结果识别对象是否发生驻留,关键就看对象的唯一标志有没有被改变。

不过,如example3所示,当你在同一行中将a和b都设置为 wtf! 的时候,Python解释器会创建一个新的对象,然后同时引用第二个变量,这时候它两的唯一标志id就是一样的。(example3仅适用于python3.7以下,后面被改了)。

example4中,发生了常量折叠,这其实也是一种优化技术。编译时表达式 ‘a’*20 会被替换成 ‘aaaaaaaaaaaaaaaaaaaa’ (不要数了,20个),不过只有长度小于20的字符串才会发生常量替换,这就是为什么 ‘a’*21并不等于 ‘aaaaaaaaaaaaaaaaaaaaa’ (不要数了,21个) 。

好,感谢大家的阅读,今天的…..等等,你以为这就结束了吗?还有呢:

>>> a = 10
>>> b = 10
>>> a is b
True
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False 

这又是为啥啊?请注意,Python中,对于整数对象,如果其值处于[-5,256]的闭区间内,则值相同的对象是同一个对象,否则为不同对象。我知道你想问,别问,问就是源码本身就这么写的(其实主要还是从性能方面考虑,-5到256这段数值被经常使用,因此干脆设为同一个对象重复使用,避免分配空间—赋予类别—赋予初始值等一系列操作)。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

2020年已到,Python2寿命已止,请迁移

随着2020年的到来,Python 2 也到来寿终正寝的时候。从2020年1月1日起,Python核心团队将不再对Python 2提供任何支持。

1.怎么办?

由于Python3不向前兼容Python2,因此对于有写过Python2,且有正在运行Python2项目的同学来说,是时候将项目迁移到Python3了。

对于正在学习Python的同学来说,不要犹豫,请直接学Python3的教程,如果某个你正在阅读的教程是Python2写的,请立即丢掉。

2.迁移方法

现在已经有许多自动化的工具可以帮你把代码从Python 2迁移到Python 3. 比如说自带的2to3模块:

2to3 的基本调用参数是一个需要转换的文件或目录列表。对于目录,会递归地寻找其中的 Python 源码。

这里有一个 Python 2.x 的源码文件,example.py

def greet(name):
    print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)

找到你的Python安装位置,一般2to3会在Tools\scripts文件夹下:C:\Python3X\Tools\scripts\2to3.py,在CMD中输入以下命令即可将Python2代码转化为Python3代码(由于我用的是anaconda,所以位置可能和你们不一样):

F:\Anaconda3\Scripts\2to3.exe example.py

它会显示所有修改,输出效果如下:

 RefactoringTool: Skipping optional fixer: buffer
 RefactoringTool: Skipping optional fixer: idioms
 RefactoringTool: Skipping optional fixer: set_literal
 RefactoringTool: Skipping optional fixer: ws_comma
 RefactoringTool: Refactored example.py
 --- example.py  (original)
 +++ example.py  (refactored)
 @@ -1,5 +1,5 @@
  def greet(name):
 print "Hello, {0}!".format(name)
 -print "What's your name?"
 -name = raw_input()
 print("Hello, {0}!".format(name))
 +print("What's your name?")
 +name = input()
 greet(name)
 RefactoringTool: Files that need to be modified:
 RefactoringTool: example.py 

如果你想写回文件,记得带-w参数:

F:\Anaconda3\Scripts\2to3.exe -w example.py

现在效果如下:

def greet(name):
    print("Hello, {0}!".format(name))
print("What's your name?")
name = input()
greet(name) 

非常方便,一键修改完成。它能转化大部分Python2代码,更详细的使用文档在这里:

https://docs.python.org/zh-cn/3.7/library/2to3.html#

不过2to3.py也不是万能的,有些情况下你只能手动地转换代码,遇到无法用工具迁移的问题,请耐心搜索解决方案

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 警惕伪装成著名软件包的恶意模块

本周早些时候,两个包含恶意代码的Python第三方模块被从官方软件PyPI中删除。这两个恶意软件包通过使用非常相似的名字来迷惑安装者。

它们伪装成dateutiljellyfish软件包 (前者用于处理日期时间,后者用于字符串近似计算等),伪装命名为python-dateutiljeIlyfish,如果安装包的时候并不熟悉这些模块,而且也没有看官方文档,那就非常有可能中招。

看,甚至有人不知道它是冒牌货

安装后, python-dateutil 和 jeIlyfish 与原始的软件包行为完全相同,但是它们会偷偷地将个人数据上传到服务器。但是正常使用的人恐怕无法发现恶意模块的这些行为。

Python通常分为两种,一种是Python运行时自带的标准,还有一种则是托管在PyPI上的第三方程序包,而上传第三方程序包到PyPI时,大部分程序包都不会被审核到。这就导致你进行pip安装的时候,如果不小心输错了单词,就有可能安装到恶意模块。

这引出了一个现在许多开软社区都非常头痛的问题:如何让人们能将自己的代码贡献到通用存储(如PyPI),且不被不怀好意的人利用。

据说,Python软件基金会已经制定了保护PyPI免受滥用的计划,但要全面执行计划需要一些时间。此外,Python软件基金会中负责封装的工作组已经获得了Facebook Research的拨款,用于开发自动检测恶意上传第三方程序包的功能。

尽管如此,这些预防措施离上线还有很远,我们在选择使用第三方模块的时候一定要注意你的命令pip install的是不是那个真的模块,而不是一个冒牌货,这样才能将风险降至最低。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

超方便的 Python 唤醒窗口自动截图脚本

利用Python自带的win32api和win32con、win32gui等模块,我们能执行许多windows下的自动化操作。比如两个窗口的自动点击操作,从软件中的窗口复制文本到txt中,甚至是截图操作。

截图的操作用途最为广泛,你可以用它配合定时工具,定时检测某个程序的运行情况;甚至可以根据截图做一些辅助性的决策,比如玩类似于《连连看》的游戏时,对相同类型的方块进行标记,辅助你玩游戏。

下面就讲讲如何使用 win32api 实现自动唤醒并截图的操作。

1.准备

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

Windows环境下打开Cmd(开始—运行—CMD),苹果系统环境下请打开Terminal(command+空格输入Terminal),输入命令安装依赖:

pip install pypiwin32
pip install pillow

1.获取窗口左上角及右下角坐标

​通过 win32gui 的 FindWindow 函数,我们能轻易地找到任何进程的窗口:

import win32api, win32con, win32gui
def get_window_pos(name):
    name = name
    handle = win32gui.FindWindow(0, name)
    # 获取窗口句柄
    if handle == 0:
        return None
    else:
        return win32gui.GetWindowRect(handle)
x1, y1, x2, y2 = get_window_pos('暴雪战网')
print(x1,y1,x2,y2)

结果:

F:\push\20190929>python 1.py
(349, 83, 1549, 1013)

其中窗口信息(x1, y1, x2, y2),(x1, y1)是窗口左上角的坐标,(x2, y2)是窗口右下角的坐标。我们可以利用这个信息配合PIL进行截图。但是在这之前,我们还要解决两个问题:

  1. 该窗口并不在当前的界面上,被其他的软件覆盖到底层中,这时候需要高亮窗口
  2. 该窗口被最小化怎么办

2.win32gui 高亮窗口

为了使得被叠在底层的窗口能放到最上层显示,我们需要拿到窗口的handle,对其执行高亮操作,其实很简单,我们刚刚获得坐标信息的时候已经得到handle了,只需要做一下简单的更改即可。

import win32api, win32con, win32gui
def get_window_pos(name):
    name = name
    handle = win32gui.FindWindow(0, name)
    # 获取窗口句柄
    if handle == 0:
        return None
    else:
        # 返回坐标值和handle
        return win32gui.GetWindowRect(handle), handle
(x1, y1, x2, y2), handle = get_window_pos('暴雪战网')
text = win32gui.SetForegroundWindow(handle)

这样就能将被覆盖到底层的窗口放到最上层,如下图所示。

python 高亮窗口

3. 还原最小化窗口

还有一种特殊情况就是窗口被缩小了,这时候我们就需要还原最小化窗口,其实也非常简单,只要利用win32gui和win32con向该窗口发送一个信息即可。

import win32api, win32con, win32gui
def get_window_pos(name):
    name = name
    handle = win32gui.FindWindow(0, name)
    # 获取窗口句柄
    if handle == 0:
        return None
    else:
        # 返回坐标值和handle
        return win32gui.GetWindowRect(handle), handle
(x1, y1, x2, y2), handle = get_window_pos('暴雪战网')
win32gui.SendMessage(handle, win32con.WM_SYSCOMMAND, win32con.SC_RESTORE, 0)
# 发送还原最小化窗口的信息
win32gui.SetForegroundWindow(handle)
# 设为高亮 

效果如图所示:

python还原最小化窗口

4.截图

有了PIL模块和窗口的坐标后,我们想截图可非常简单。PIL 模块安装

pip install pillow

安装完就可以试一下我们的完整代码了,如下:

import win32api, win32con, win32gui

def get_window_pos(name):
    name = name
    handle = win32gui.FindWindow(0, name)
    # 获取窗口句柄
    if handle == 0:
        return None
    else:
        # 返回坐标值和handle
        return win32gui.GetWindowRect(handle), handle
(x1, y1, x2, y2), handle = get_window_pos('暴雪战网')
win32gui.SendMessage(handle, win32con.WM_SYSCOMMAND, win32con.SC_RESTORE, 0)
# 发送还原最小化窗口的信息
win32gui.SetForegroundWindow(handle)
# 设为高亮
from PIL import Image, ImageGrab
img_ready = ImageGrab.grab((x1, y1, x2, y2))
# 截图
img_ready.show()
# 展示 

效果如下:

python 截图

这个功能可好用了,比如说你需要监控一个窗口的运行状况,不可能时时刻刻都去观察它,你可以使用while循环不断调用这个窗口截图脚本,先截图进行保存。

你甚至可以配合定时任务做截图,见我们上篇文章:Schedule—简单实用的 Python 周期任务调度工具

截图后的图表信息还能够用于分析、辅助决策。举个游戏的例子:当你玩《连连看》的时候,可以截图检测每个方块是否相同,把相同的方块标记出来,提高你的连连看游戏效率。

我们的文章到此就结束啦,如果你喜欢今天的Python 实战教程,请持续关注Python实用宝典。原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

Python 使用VS Code进行调试

VS Code是一款非常好用的编辑器,现在我基本上所有的开发任务都在VS Code上完成。它的代码调试工具其实也非常强大,但是许多人都不知道该怎么用,今天就来学习怎么用它调试Python代码吧。

1.准备

既然是用VS Code调试Python代码,那当然你得先安装好Python啦,如果你还没有安装,可以看这篇文章:超详细Python安装指南

除此之外,确保你已经安装了最新版本的VS Code: https://code.visualstudio.com/ 。安装完成后,记得还要安装Python扩展,打开VS Code,如下图所示安装Python扩展:

2.配置调试环境

打开VS Code的DEBUG设置,先点击左边的虫子,再点击上面的齿轮:

点击后提示选择一种语言,选择Python。然后要指定相应的文件类型,可以看到,它支持许多种Python的调试方法,有Django, Flask, 甚至是 Pyramid. 由于下面我们要讲的只是单文件的代码调试,因此选择Python File.

然后会自动在当前文件夹的根目录/.vscode中生成一个launch.json的配置文件,打开后你会发现长这个样子:

下面是这些字段的说明:

1.name: 当前DEBUG配置的名称。

2.Type: 指什么语言。

3.request是最重要的参数,它能选择两种类型,一个是launch模式,一个是attach模式:

launch模式:由VS Code来启动一个独立的具有debug功能的程序。

attach模式:监听一个已启动的程序(其必须已经开启debug模式)。

大多数情况下,调试Python都是用launch模式。少数情况下,你无法通过新建独立程序来调试(如要与浏览器相结合的程序,launch模式会导致你大部分浏览器插件失效),这时候就需要attach模式。

4.program: 文件的绝对路径,一般不需要改动。

5.console: 终端的类型, integratedTerminal 指使用vscode终端。

当然,我们还可以设置其他参数,比如 stopOnEntry: true , 可以在进入程序的时候就暂停执行:

3.编写一段调试用的代码

我们先随便编写一串代码,来演示怎么查看变量的值:

import random
a = random.randint(0,100)
b = random.randint(0,100)
print(a*b) 

打开debug面板,点击绿色的播放按钮,就会在代码块上方出现一个控制条,点击单步调试,就能够一行行地执行代码:

第二行执行完毕后,左边便会出现a变量相应的值:

这样,通过调试,你能清楚知道a*b的结果中,a和b分别对应的值。

但是,在工作生活中,我们自己写的模块、代码很少有需要调试的时候。只有当我们使用别的人框架或者别人的开源模块时,才时常会遇到问题,这时候调试工具才能发挥出最大的功效,比如下面这个例子:

import sys
f = open('20191206/myfile.txt')
s = f.readline()
print(s) 

像这种编码问题,用调试工具是非常容易解决的:

先打一个断点:

进行调试,运行到报错的这一句话时,左边有f对象的详细信息,点击后可以看到encoding参数是cp936,而我们文件里的字符串本身是utf-8的,因此,我们在打开文件的时候要设置打开编码。

修改代码如下即可正常运行:

import sys
f = open('20191206/myfile.txt', encoding='utf-8')
s = f.readline()
print(s) 

调试工具的强大还不止如此,VS Code还有监视和调用堆栈的查看功能,虽然整体上并不如pycharm,但是对于我们中小型项目的调试其实是完全足够了。

VsCode系列文章:

Python 使用VS Code进行调试

VSCode 设置中文

Python 编程的最好搭档—VSCode 详细指南

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

教你怎么用 Python 自动一键整理文件

Python 自动整理文件是一个非常容易实现的工具。以前,我经常习惯性地把下载下来的东西放在桌面或者下载文件夹中,使用完后再也没管它,久而久之桌面便变得乱七八糟到后面再整理的时候就非常痛苦了,巴不得有一个自动整理的工具帮我归类文档。

不知道你是不是有过跟我一样糟糕的体验,不过,我们现在完全可以用Python做一个这样的工具来根据后缀名整理文件先来看看效果:

自动整理前:

自动整理后:

效果非常好,舒服多了如果你想要直接下载源代码试试看,请关注文章最下方的Python实用宝典公众号,后台回复 文件自动整理 获得源代码下载地址。

1.一键整理文件

开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,请访问这篇文章:超详细Python安装指南 进行安装。

(可选1) 如果你用Python的目的是数据分析,可以直接安装Anaconda:Python数据分析与挖掘好帮手—Anaconda,它内置了Python和pip.

(可选2) 此外,推荐大家用VSCode编辑器来编写小型Python项目:Python 编程的最好搭档—VSCode 详细指南

你只需要修改源代码主程序中调用 auto_organize 函数的参数即可完成对对应文件的整理,比如我想整理  C:\Users\83493\Downloads 文件夹:

if __name__ == "__main__":    auto_organize(r"C:\Users\83493\Downloads")

如上所示,修改代码第61行的文件夹地址即可。修改完成后运行该脚本:

python auto_files.py

就能瞬间完成对指定文件夹的整理,极其方便。

你只需要修改源代码主程序中调用 auto_organize函数的参数即可完成对对应文件的整理,比如我想整理  C:\Users\83493\Downloads 文件夹:

if __name__ == "__main__":    auto_organize(r"C:\Users\83493\Downloads")


如上所示,修改代码第61行的文件夹地址即可。修改完成后运行该脚本:

python auto_files.py

就能瞬间完成对指定文件夹的整理,极其方便:

2.整理文件原理

为了整理这些文件,我们要遍历当前指定的文件夹:如果是文件夹则跳过,如果是文件则检测后缀,分类到对应的文件夹中。文件夹名字及其对应的文件后缀如下:

DIRECTORIES = {
    "图片": [".jpeg", ".jpg", ".tiff", ".gif", ".bmp", ".png", ".bpg", "svg",
               ".heif", ".psd"],
    "视频": [".avi", ".flv", ".wmv", ".mov", ".mp4", ".webm", ".vob", ".mng",
               ".qt", ".mpg", ".mpeg", ".3gp", ".mkv"],
    "文档": [".oxps", ".epub", ".pages", ".docx", ".doc", ".fdf", ".ods",
             ".odt", ".pwi", ".xsn", ".xps", ".dotx", ".docm", ".dox",
             ".rvg", ".rtf", ".rtfd", ".wpd", ".xls", ".xlsx", ".ppt",
             "pptx",".csv",",pdf"],
    "压缩文件": [".a", ".ar", ".cpio", ".iso", ".tar", ".gz", ".rz", ".7z",
                ".dmg", ".rar", ".xar", ".zip"],
    "影音": [".aac", ".aa", ".aac", ".dvf", ".m4a", ".m4b", ".m4p", ".mp3",
             ".msv", "ogg", "oga", ".raw", ".vox", ".wav", ".wma"],
    "文本": [".txt", ".in", ".out"],
    "编程": [".py",".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    "可执行程序": [".exe"],
}

接下来是自动整理的部分代码,先遍历指定的文件夹,识别后缀并分类到对应的文件夹中。

    for entry in os.scandir(dirval):
        if entry.is_dir():
            # 如果是文件夹则跳过
            continue
        file_path = Path(dirval + "\\" + entry.name)
        file_format = file_path.suffix.lower()
        # 避免后缀大小写判断问题,全转为小写
        if file_format in FILE_FORMATS:
            directory_path = Path(dirval + "\\" + FILE_FORMATS[file_format])
            directory_path.mkdir(exist_ok=True)
            file_path.rename(directory_path.joinpath(entry.name))

还有出现不存在在我们字典里的后缀的情况,把它们分类到名为 其他文件 的文件夹中:

    try:
        os.mkdir(dirval + "\\" +"其他文件")
    except:
        pass

    for dir in os.scandir(dirval):
        try:
            if dir.is_dir():
                # 删除空文件夹
                os.rmdir(dir)
            else:
                temp = str(Path(dir)).split('\\')
                # 分割文件路径
                path = '\\'.join(temp[:-1])
                print(path + '\\其他文件\\' + str(temp[-1]))
                os.rename(str(Path(dir)), path + '\\其他文件\\' + str(temp[-1]))
        except:
            pass

最后再把以上这些部分整理成函数即可。关注文章最下方的Python实用宝典公众号,后台回复 文件自动整理 获得源代码下载地址。

3.自定义整理

如果你并不想按照设定好的文件整理,希望能自定义地将某些特定后缀的文件放到另一个文件夹,比如 .py 文件统一收纳到“Python脚本”文件夹中,你可以这么改 DIRECTORIES 变量:

改动前:

DIRECTORIES = {
    # ......
    "编程": [".py",".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    # ......
}

改动后:

DIRECTORIES = {
    # ......
    "编程": [".html5", ".html", ".htm", ".xhtml",".c",".cpp",".java",".css"],
    "Python脚本": [".py"],
    # ......
}

你可以按照这个方法,自定义收纳那些你需要整理收纳的文件格式。

如果你只想对 DIRECTORIES 变量里那些后缀的文件进行整理,不属于这些后缀的文件则不进行整理,不需要放到“其他文件”目录下,此时要怎么做?

很简单,你只需要删除以下部分代码就可以完成这个功能:

# ......
    try:
        os.mkdir(dirval + "\\" +"其他文件")
    except:
        pass

    for dir in os.scandir(dirval):
        try:
            if dir.is_dir():
                # 删除空文件夹
                os.rmdir(dir)
            else:
                temp = str(Path(dir)).split('\\')
                # 分割文件路径
                path = '\\'.join(temp[:-1])
                print(path + '\\其他文件\\' + str(temp[-1]))
                os.rename(str(Path(dir)), path + '\\其他文件\\' + str(temp[-1]))
        except:
            pass
# ......

怎么样,是不是很方便?如果喜欢的话记得给我点个赞哦。

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!

​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典