分类目录归档:算法

Python 全自动解密解码神器 — Ciphey

Ciphey 是一个使用自然语言处理和人工智能的全自动解密/解码/破解工具。

简单地来讲,你只需要输入加密文本,它就能给你返回解密文本。就是这么牛逼。

有了Ciphey,你根本不需要知道你的密文是哪种类型的加密,你只知道它是加密的,那么Ciphey就能在3秒甚至更短的时间内给你解密,返回你想要的大部分密文的答案。

下面就给大家介绍 Ciphey 的实战使用教程

1.准备

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

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

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

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

pip install -U ciphey

2.Ciphey 基本使用

有3种方法可以运行 Ciphey:

1. 文件输入:

ciphey -f encrypted.txt
# 或
python -m ciphey -f encrypted.txt

2.不规范的方法:

ciphey -- "Encrypted input"
# 或
python -m ciphey -- "Encrypted input"

3.正常方式

ciphey -t "Encrypted input"
# 或
python -m ciphey -t "Encrypted input"

如下图所示:

要去除进度条、概率表和所有噪音,请使用安静模式:

ciphey -t "encrypted text here" -q

3.在Python中调用Ciphey

如果你需要在Python中使用Ciphey,请这样使用:

# Python实用宝典
# 2021/07/19
from ciphey.__main__ import main, main_decrypt, make_default_config
main_decrypt(make_default_config("SGVsbG8gbXkgbmFtZSBpcyBiZWUgYW5kIEkgbGlrZSBkb2cgYW5kIGFwcGxlIGFuZCB0cmVl"))
# >> Hello my name is bee and I like dog and apple and tree

运行后会输出如下的结果:

效果还是相当不错的,如果你不想输出概率表,只想要解密内容,代码需要这么写:

# Python实用宝典
# 2021/07/19
from ciphey.__main__ import main, main_decrypt, make_default_config
config = make_default_config("SGVsbG8gbXkgbmFtZSBpcyBiZWUgYW5kIEkgbGlrZSBkb2cgYW5kIGFwcGxlIGFuZCB0cmVl")
config["grep"] = True
main_decrypt(config)
# >> Hello my name is bee and I like dog and apple and tree

非常Nice,你根本无需知道这是什么编码。

Ciphey 支持解密的密文和编码多达51种,下面列出一些基本的选项

基本密码:

  • Caesar Cipher
  • ROT47 (up to ROT94 with the ROT47 alphabet)
  • ASCII shift (up to ROT127 with the full ASCII alphabet)
  • Vigenère Cipher
  • Affine Cipher
  • Binary Substitution Cipher (XY-Cipher)
  • Baconian Cipher (both variants)
  • Soundex
  • Transposition Cipher
  • Pig Latin

现代密码学:

  • Repeating-key XOR
  • Single XOR

编码:

  • Base32
  • Base64
  • Z85 (release candidate stage)
  • Base65536 (release candidate stage)
  • ASCII
  • Reversed text
  • Morse Code
  • DNA codons (release candidate stage)
  • Atbash
  • Standard Galactic Alphabet (aka Minecraft Enchanting Language)
  • Leetspeak
  • Baudot ITA2
  • URL encoding
  • SMS Multi-tap
  • DMTF (release candidate stage)
  • UUencode
  • Braille (Grade 1)
  • ……

Ciphey 的功能不仅于本文介绍的这些,本文所介绍的只是冰山一角,它还可以添加属于你自己的解码器:

https://github.com/Ciphey/Ciphey/wiki/Adding-your-own-ciphers

如果要进一步的学习,你可以在上述 Ciphey 的 Github Wiki 介绍中,查阅到更多的资料,进行更深层次的学习。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

Python替换字符串的新工具 FlashText!比正则快M倍以上!

FlashText算法是由Vikash Singh于2017年发表的大规模替换字符串算法,这个算法的时间复杂度仅由文本长度(N)决定,算法时间复杂度为O(N)。

而对于正则表达式的替换,算法时间复杂度还需要考虑被替换的关键词数量(M),因此时间复杂度为O(MxN)。

简而言之,基于FlashText算法的字符串替换比正则表达式替换快M倍以上,这个M是需要替换的关键词数量,关键词越多,FlashText算法的优势就越明显

下面就给大家介绍如何在 Python 中基于 flashtext 模块使用 FlashText 算法进行字符串查找和替换,如果觉得对你的项目团队很有帮助,请记得帮作者转发一下哦。

1.准备

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

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

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

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

pip install flashtext

2.FlashText基本使用—替换字符串

提取关键词

一个最基本的提取关键词的例子如下:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 添加关键词
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
# 3. 处理目标句子并提取相应关键词
keywords_found = keyword_processor.extract_keywords('I love Big Apple and Bay Area.')
# 4. 结果
print(keywords_found)
# ['New York', 'Bay Area']

其中 add_keyword 的第一个参数代表需要被查找的关键词,第二个参数是给这个关键词一个别名,如果找到了则以别名显示。

替换关键词

如果你想要替换关键词,只需要调用处理器的 replace_keywords 函数:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 添加关键词
keyword_processor.add_keyword('New Delhi', 'NCR region')
# 3. 替换关键词
new_sentence = keyword_processor.replace_keywords('I love Big Apple and new delhi.')
# 4. 结果
print(new_sentence)
# 'I love New York and NCR region.'

关键词大小写敏感

如果你需要精确提取,识别大小写字母,那么你可以在处理器初始化的时候设定 sensitive 参数:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器, 注意设置大小写敏感(case_sensitive)为TRUE
keyword_processor = KeywordProcessor(case_sensitive=True)
# 2. 添加关键词
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
# 3. 处理目标句子并提取相应关键词
keywords_found = keyword_processor.extract_keywords('I love big Apple and Bay Area.')
# 4. 结果
print(keywords_found)
# ['Bay Area']

标记关键词位置

如果你需要获取关键词在句子中的位置,在 extract_keywords 的时候添加 span_info=True 参数即可:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 添加关键词
keyword_processor.add_keyword('Big Apple', 'New York')
keyword_processor.add_keyword('Bay Area')
# 3. 处理目标句子并提取相应关键词, 并标记关键词的起始、终止位置
keywords_found = keyword_processor.extract_keywords('I love big Apple and Bay Area.', span_info=True)
# 4. 结果
print(keywords_found)
# [('New York', 7, 16), ('Bay Area', 21, 29)]

获取目前所有的关键词

如果你需要获取当前已经添加的所有关键词,只需要调用处理器的get_all_keywords 函数:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 添加关键词
keyword_processor.add_keyword('j2ee', 'Java')
keyword_processor.add_keyword('colour', 'color')
# 3. 获取所有关键词
keyword_processor.get_all_keywords()
# output: {'colour': 'color', 'j2ee': 'Java'}

批量添加关键词

批量添加关键词有两种方法,一种是通过词典,一种是通过数组:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. (第一种)通过字典批量添加关键词
keyword_dict = {
    "java": ["java_2e", "java programing"],
    "product management": ["PM", "product manager"]
}
keyword_processor.add_keywords_from_dict(keyword_dict)
# 2. (第二种)通过数组批量添加关键词
keyword_processor.add_keywords_from_list(["java", "python"])
# 3. 第一种的提取效果如下
keyword_processor.extract_keywords('I am a product manager for a java_2e platform')
# output ['product management', 'java']

单一或批量删除关键词

删除关键词也非常简单,和添加类似:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 通过字典批量添加关键词
keyword_dict = {
    "java": ["java_2e", "java programing"],
    "product management": ["PM", "product manager"]
}
keyword_processor.add_keywords_from_dict(keyword_dict)
# 3. 提取效果如下
print(keyword_processor.extract_keywords('I am a product manager for a java_2e platform'))
# ['product management', 'java']
# 4. 单个删除关键词
keyword_processor.remove_keyword('java_2e')
# 5. 批量删除关键词,也是可以通过词典或者数组的形式
keyword_processor.remove_keywords_from_dict({"product management": ["PM"]})
keyword_processor.remove_keywords_from_list(["java programing"])
# 6. 删除了java programing关键词后的效果如下
keyword_processor.extract_keywords('I am a product manager for a java_2e platform')
# ['product management']

3.FlashText 高级使用

支持额外信息

前面提到在添加关键词的时候第二个参数为其别名,其实你不仅可以指示别名,还可以将额外信息放到第二个参数中:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
kp = KeywordProcessor()
# 2. 添加关键词并附带额外信息
kp.add_keyword('Taj Mahal', ('Monument', 'Taj Mahal'))
kp.add_keyword('Delhi', ('Location', 'Delhi'))
# 3. 效果如下
kp.extract_keywords('Taj Mahal is in Delhi.')
# [('Monument', 'Taj Mahal'), ('Location', 'Delhi')]

这样,在提取关键词的时候,你还能拿到其他一些你想要在得到此关键词时输出的信息。

支持特殊单词边界

Flashtext 检测的单词边界一般局限于 \w [A-Za-z0-9_] 外的任意字符,但是如果你想添加某些特殊字符作为单词的一部分也是可以实现的:

from flashtext import KeywordProcessor
# 1. 初始化关键字处理器
keyword_processor = KeywordProcessor()
# 2. 添加关键词
keyword_processor.add_keyword('Big Apple')
# 3. 正常效果
print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.'))
# ['Big Apple']
# 4. 将 '/' 作为单词一部分
keyword_processor.add_non_word_boundary('/')
# 5. 优化后的效果
print(keyword_processor.extract_keywords('I love Big Apple/Bay Area.'))
# []

4.结尾

个人认为这个模块已经满足我们的基本使用了,如果你有一些该模块提供的功能之外的使用需求,可以给 flashtext 贡献代码:
https://github.com/vi3k6i5/flashtext

附 FlashText 与正则相比 查询关键词 所花费的时间之比:

附 FlashText 与正则相比 替换关键词 所花费的时间之比:

这篇文章如果对你有帮助的话,记得转发一下哦。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

超简单教你用Python克隆卷福的声音

语音克隆是这两年比较火的深度学习应用,它允许从几秒钟的音频中学习对象的说话方式和音调,并使用它来生成新的语音。

下面来看看我使用 SV2TTS 训练模仿卷福阅读下面这句话的效果:

She is beginning to get many wrinkles around her eyes.

训练集:

克隆、模仿效果(She is beginning to get many wrinkles around her eyes.):

https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2021/03/2021031017113638.wav

效果不错,如果不知道它是生成的,还以为真的是卷福念的。

下面就来教大家如何使用 Real-Time-Voice-Cloning 项目克隆语音并生成自己想要的语句。

1.准备

大家可以前往 Real-Time-Voice-Cloning 项目下载这个项目的代码以及预训练完成的模型。(注意,需要Python 3.6以上才能运行该项目)

如果你的网络速度比较差,下载不了 github 项目及其预训练模型,可以在 Python 实用宝典 公众号后台回复 克隆语音 下载完整项目代码及预训练模型。

下载完项目代码后,你还需要下载两个重要依赖:

安装 PyTorch

其中,PyTorch的官方指南已经写得很清楚了,大家根据自己的需求安装即可。

安装 ffmpeg

而 ffmpeg 的安装我们已经在这篇文章详细地讲过:Python 多种音乐格式转换(批量)实战教程,在此重新讲解一下:

Mac (打开终端(Terminal), 用 homebrew 安装):

brew install ffmpeg --with-libvorbis --with-sdl2 --with-theora

Linux:

apt-get install ffmpeg libavcodec-extra

Windows:

1. 进入 http://ffmpeg.org/download.html#build-windows,点击 windows 对应的图标,进入下载界面点击 download 下载按钮,
2. 解压下载好的zip文件到指定目录
3. 将解压后的文件目录中 bin 目录(包含 ffmpeg.exe )添加进 path 环境变量中

安装模块依赖

安装完成以上两个重要依赖后,在终端、命令行中进入项目目录中,安装依赖:

pip install -r requirements.txt

这会安装所有 requirements.txt 中的所有依赖。

2.下载预训练模型(可选)

如果你用的是我们提供的项目文件,你就不需要再进行这一步了,因为把预训练的模型都已经放进去了。

如果你没有用Python实用宝典提供的项目代码,你还需要去下载预训练的模型:

https://github.com/CorentinJ/Real-Time-Voice-Cloning/wiki/Pretrained-models

下载完成后解压 pretrained.zip 分别将对应的模型放入项目对应的位置中:

encoder\saved_models\pretrained.pt
synthesizer\saved_models\pretrained\pretrained.pt
vocoder\saved_models\pretrained\pretrained.pt

3.试一下克隆语音

随便选取一段你想要克隆的人的语音,大概30秒左右,放入项目文件夹中。然后在该文件夹中运行命令:

python demo_cli.py

如果一切正常,它会出现让你选择训练语音文件:

此时输入你准备好的一段语音,等待它训练完成后,它会让你输入想要模仿的文字:

比如上图中,我输入了:

She is beginning to get many wrinkles around her eyes.

程序生成完毕后会自动念出克隆结果,如果你没有听见克隆结果,没关系,程序会将其保存在当前文件夹下,命名为 demo_output_xx.wav.

双击打开这个文件,就是它生成的语音克隆结果啦,听听看,是不是你想要的效果?

如果没有达到你的理想效果,请检查一下训练集是否有杂音、时间够不够长、有没有其他人的介入,这些因素都可能导致克隆效果不理想。

我们的文章到此就结束啦,如果你喜欢今天的 Python 教程,请持续关注Python实用宝典。

有任何问题,可以在公众号后台回复:加群,回答相应验证信息,进入互助群询问。

原创不易,希望你能在下面点个赞和在看支持我继续创作,谢谢!

给作者打赏,选择打赏金额
¥1¥5¥10¥20¥50¥100¥200 自定义

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

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实用宝典

Python 重载与重写 及 泛型函数

在上一次的推送《Python 监控文件事件变化—以音乐高潮提取为例》中,最后继承 LoggingEventHandler 类,对 on_created 进行修改的时候,我使用了一个词叫:重载,随后不久我便意识到犯下了一个错误。

我们先来看看重载与重写的概念:

重载:

重载的条件如下:

1.一个类里面

2.方法名字相同

3.参数不同

而参数不同可分为:参数类型不同,参数个数不同。而上一次推送中,对on_created的修改并没有针对参数,我们只是单纯地对函数内容进行修改而已。因此只能叫重写

重写:

条件如下:

1.参数列表与原函数一致。

2.返回类型与原函数一致。

因此,根据这个条件,Python中绝大部分的继承修改只能叫重写,而不能叫重载

Python其实不需要重载这个概念。为什么呢?重载主要是针对参数而言的,一个是改变参数的类型,一个是改变参数的个数。而Python不需要限定参数类型,又 可以接受可变参数,因此函数重载就显得非常鸡肋了。

不过我们依然能通过singledispatch装饰器来实现重载,不过官方称其为泛型函数:

在需要被重载的函数上加上装饰器:

from functools import singledispatch


@singledispatch
def fun(arg, verbose=False):
    if verbose:
        print("Let me just say,", end=" ")
    print(arg) 

然后用register属性注册重载后的函数:

@fun.register(int)
def _(arg: int, verbose=False):
    if verbose:
        print("Strength in numbers, eh?", end=" ")
    print(arg)


@fun.register(list)
def _(arg: list, verbose=False):
    if verbose:
        print("Enumerate this:")
    for i, elem in enumerate(arg):
        print(i, elem) 

效果如下:

>>> fun(42, verbose=True)
Strength in numbers, eh? 42

>>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True)
Enumerate this:
0 spam
1 spam
2 eggs
3 spam 

看,这样我们就顺利完成了重载,尽管其实大部分时候都不会用到。

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


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

庆祝胖五发射成功, 来用Python发射火箭!

今天看到了一则可喜可贺的消息:长征五号遥三运载火箭在中国文昌航天发射场点火升空,与实践二十号卫星成功分离,任务取得圆满成功。 真是令人自豪,为这些辛苦工作的航天人喝彩。

不过,火箭发射似乎离我们普通人太远了,如果我们想体验一把亲自将火箭送上天的感觉怎么办呢?好像很难啊?没关系,Python有方法,现实世界里做不到,但是你可以在虚拟世界里实现。

《坎巴拉太空计划》就是一个能让你实现这个愿望的一款游戏。在这个游戏中,玩家拥有一支庞大的航天团队,能够造出你想要的任意航天器,你也可以驾驶航天器在坎巴拉星系中遨游,建立太空站。

更重要的是,它!支持!Python!

你可以使用Python来画你想要的航天器、设置警报、航天器之间的通讯、控制运行轨道、监控燃料量等等一系列功能,甚至能够改变游戏界面。

在Space Center API中,你可以读取作用在飞船上的重力、获得海拔高度、绕行轨道的纬度、参考系速度、控制游戏内部相机等等,几乎一切想读取的它都可以读取到。

1.安装

你可以通过pip安装这个项目:

pip install krpc

如果你还没有安装python,请看这篇文章:安装Python

注意,使用这个项目的前提是先下载好游戏。而且在运行脚本的时候,游戏必须在运行着,并与客户端保持连接。怎样才能和客户端连接呢?你还需要下载kRPC服务器插件:

https://github.com/krpc/krpc/releases/download/v0.4.8/krpc-0.4.8.zip

然后执行以下操作:

  1. 提取gamedata文件夹到您的KSP目录。
  2. 启动游戏。
  3. 这时候应该就会弹出服务器窗口

2.使用

运行游戏,并且服务器正常启动后,我们就可以开始尝试一些例子了。不过在这之前,Python脚本作为客户端还需要和服务器进行连接:

import krpc
conn = krpc.connect(name='Hello World')
vessel = conn.space_center.active_vessel
print(vessel.name) 

第二行连接服务器,第三行获得激活的飞行器、第四行打印飞行器名字:

你还可以尝试一些别的API,比如下面这个例子,能够获得飞行棋相对于参照物(行星)的速度:

import krpc, time
conn = krpc.connect(name='Surface speed')
vessel = conn.space_center.active_vessel

while True:

    velocity = vessel.flight(vessel.orbit.body.reference_frame).velocity
    print('Surface velocity = (%.1f, %.1f, %.1f)' % velocity)

    speed = vessel.flight(vessel.orbit.body.reference_frame).speed
    print('Surface speed = %.1f m/s' % speed)

    time.sleep(1) 

如果你们感兴趣,推荐先下载游戏并试玩,大致摸清楚游戏的玩法后,开始使用Python来进行编程游戏。说实话,这个游戏太适合用来教小孩子了。

Python和游戏之间详细的API都在这里可以找得到:

http://krpc.github.io/krpc/python.html

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


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