2021-05-27 Python小技巧

目录


一、(浅shallow)拷贝(copy)和深拷贝(deep copy)的区别:

# Python

>>> from copy import copy, deepcopy
>>> ll = [[1, 2], [3, 4]]
>>> ll2 = copy(ll)
>>> ll3 = deepcopy(ll)
>>> ll[0][0] = 10
>>> ll
[[10, 2], [3, 4]]
>>> ll2
[[10, 2], [3, 4]]
>>> ll3
[[1, 2], [3, 4]]

:需要先安装deepcopy,语句from copy import copy, deepcopy才不会报错。

# Python
>>> pip install deepcopy
图片.png

一、difflib.get_close_matches - 模糊匹配的朋友:

Python中的difflib.get_close_matches模块你用来对字符串进行模糊匹配处理的朋友,比如当用户拼写错误时,我们想要建议一个紧密匹配的名称。这是一个内置的库,不需要安装:

# Python
>>> import difflib
>>> from difflib import get_close_matches
>>> names = ("tim", "sara", "nancy", "henrik")
>>> get_close_matches("fancy", names)
['nancy']
>>> get_close_matches("zara", names)
['sara']
>>> get_close_matches("henrico", names)
['henrik']
图片.png

getattr方法

Python中的getattr方法一定会让您大吃一惊,请记住这一点(来自文档):
“如果指定的属性不存在,就返回默认值(如果有的话),否则就会引发AttributeError的例外信息”:

# Python

>>> class Foo:  
...     bar = 1
... 
>>> f = Foo()
>>> getattr(f, "bar")
1
>>> getattr(f, "bar2") 
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'Foo' object has no attribute 'bar2'
>>> getattr(f, "bar2", 2) 
2
图片.png

获取当前工作日

在Python中如何知道当天是星期几?

# Python

>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2021, 5, 27, 10, 46, 27, 161788)
>>> datetime.now().strftime("%A")
'Thursday'
>>> datetime.now().strftime("%a") 
'Thu'
图片.png

使用splitlines()函数拆分文本

如果您使用的是Windows或(旧)Apple计算机(它们分别是用\ r\n\r来进行换行的),那么使用Python的split("\n")函数将文本拆分为行,就有可能会返回很奇怪的结果。
在这
在这种情况下,使用splitlines()就是一个更安全的选择:

# Python

>>> "first line\r\nsecond line".split("\n")
['first line\r', 'second line']
>>> "first line\r\nsecond line".splitlines()    
['first line', 'second line']
>>> "first line\rsecond line".splitlines()  
['first line', 'second line']
>>> "first line\nsecond line".splitlines() 
['first line', 'second line']
图片.png

dict推导式反转字典的键和值

使用dict推导式来反转Python的键和值

# Python

>>> belts = {10: "white", 50: "yellow", 100: "orange", 175: "green", 250: "blue"}  
>>> {belt: score for score, belt in belts.items()}
{'white': 10, 'yellow': 50, 'orange': 100, 'green': 175, 'blue': 250}
图片.png

timedelta在其字符串表示形式中使用divmod

有趣的是,看看Pythontimedelta是如何在其字符串表示形式中使用divmod

# Python

>>> def __str__(self):
...     mm, ss = divmod(self._seconds, 60)
...     hh, mm = divmod(mm, 60)
... 
>>> from datetime import timedelta
>>> timedelta(seconds=4000)
>>> timedelta(seconds=4000)     
datetime.timedelta(seconds=4000)
>>> print(str(timedelta(seconds=4000)))
1:06:40
图片.png

从某条日志记录中提取datetime

如何使用Python从某条日志记录中提取datetime(或者,您可以使用dateutil.parser.parse,但这个模块不是标准库)

# Python

>>> line = "INFO 2014-07-03T23:27:51 supybot Shutdown complete" 
>>> timestamp = line.split()[1] 
>>> timestamp
'2014-07-03T23:27:51'
>>> from datetime import datetime
>>> datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S") 
datetime.datetime(2014, 7, 3, 23, 27, 51)
图片.png

datetime类的fromtimestamp类方法

Python的datetime类有一个fromtimestamp类方法,可以从POSIX时间戳中创建datetime对象,例如:

# Python

>>> tstamp = time()
>>> tstamp
1622112421.3426158
>>> from datetime import datetime
>>> datetime.fromtimestamp(tstamp)  
datetime.datetime(2021, 5, 27, 18, 47, 1, 342616)
>>>
图片.png

解析博客供稿的一些常见类别

解析博客供稿的一些常见类别:

# Python

>>> import xml.etree.ElementTree as ET  
>>> from collections import Counter
>>> import requests
>>> resp = requests.get("https://pybit.es/feeds/all.rss.xml")
>>> tree = ET.fromstring(resp.content)
>>> categories = (e.text for e in tree.findall("./channel/item/category"))
>>> Counter(categories).most_common(5)
[('learning', 102), ('news', 98), ('twitter', 96), ('python', 88), ('tips', 75)]
图片.png

检查某个对象是否是内建的

这个Python对象是内置的吗?

# Python

>>> from inspect import isbuiltin
>>> def func():
...     pass
... 
>>> isbuiltin(func)
False
>>> isbuiltin(any)
True
>>> isbuiltin(sorted)
True
图片.png

选择一个随机元素

从某个Python范围中选择一个随机元素:

# Python

>>> from random import randrange
>>> randrange(25, 51, 5) 
40  
>>> randrange(25, 51, 5)
25
>>> randrange(25, 51, 5)
50
>>> randrange(25, 51, 2)
43
图片.png

collections.Counter太神奇了!

collections.Counter真的是太神奇了:

# Python

>>> from collections import Counter
>>> languages = "Python Jave Perl Python JS C++ JS Python".split()
>>> Counter(languages)
Counter({'Python': 3, 'JS': 2, 'Jave': 1, 'Perl': 1, 'C++': 1})
>>> Counter(languages).most_common(2)
[('Python', 3), ('JS', 2)]
图片.png

__str____repr__的区别

Python中的__str____repr__有什么区别?

内德·巴切德尔(Ned Batchelder)说得好:“我的经验法则是:__repr__是为开发人员设计的,而__str__则是为客户开发的。(”https://stackoverflow.com/a/1438297)

# Python

>>> from datetime import date
>>> today = date.today()
>>> str(today)
'2021-05-28'
>>> repr(today)
图片.png

删除所有前导空白

测试代码输出时一种有用的技术就是删除所有前导空白。

您可以为此使用inspect.cleandoctextwrap.dedent,这是前者的一个示例:

# Pyhton

from inspect import cleandoc


def test_uesr_selects_tree_emoji(capfd):
    actual = capfd.readouterr()[0].strip()
    expected = cleandoc("""
    1 
    2 
    3 
    4 
    5 
    """)
    assert actual == expected

编码所使用的操作系统/系统

嗨,Python,我今天是在什么操作系统或系统上进行编码的?

# Python

>>> import platform
>>> platform.machine()
'AMD64'
>>> platform.node()
'VICTOR_2ND_LAPT'
>>> platform.system()
'Windows'
编码所使用的操作系统/.png

计算两个日期之间的天数

当自己开发的自动化工具能够对重要的日期进行提醒的时候,总是很有趣的。

比如,你能相信到今天我们已经存在1600多天了吗?

当然这需要通过Python来表达它:

# Python

>>> # 28th of May 2021
>>> from datetime import date
>>> date.today() - date(2016, 12, 19)
datetime.timedelta(days=1621)
图片.png

从特定数字开始的计数器

如果在Python中您需要一个从特定数字开始的计数器,那么就可以使用itertools.count

# Python

>>> from itertools import count
>>> counter = count(1001)
>>> next(counter)
1001
>>> next(counter)
1002
>>> counter = count(1001, step=2)
>>> next(counter)
1001
>>> next(counter)
1003
从特定数字开始的计数器.png

理解非英语日期字符串:

使用Python的dateparser(PyPI)理解非英语日期字符串:

# Python

>>> date = "5 de mayo de 2021"
>>> from dateparser import parse
>>> parse(date)
datetime.datetime(2021, 5, 5, 0, 0)

:其中的5 de mayo de 2021为西班牙语。中文也可以识别:

# Python

>>> from dateparser import parse
>>> date = "2021年5月5日"
>>> parse(date)
datetime.datetime(2021, 5, 5, 0, 0)
>>> date = "2021年5月25日"
>>> parse(date)
datetime.datetime(2021, 5, 25, 0, 0)
理解非英语日期字符串.png

:需要预先安装dateparser库。


抓取某个博客中所有包含class字样文章的标题:

使用requestsBeautiful Soup来抓取https://pybit.es/的博客,查找包含class字样文章的标题:

# Python

>>> from pprint import pprint as pp
>>> import bs4
>>> import requests
>>> resp =requests.get("https://pybit.es/archives")
>>> soup = bs4.BeautifulSoup(resp.text, "html.parser")
>>> articles = [link["href"] for link in soup.find_all("a", href=True) if "class" in link.text.lower()]
>>> pp(articles)
['https://pybit.es/when-classes.html',
 'https://pybit.es/codechallenge24_review.html',
 'https://pybit.es/codechallenge24.html',
 'https://pybit.es/python-subclasses.html',
 'https://pybit.es/python-classes.html']
抓取博客文章.png

namedtuple添加类型提示

namedtuple添加类型提示:

# Python

>>> from typing import NamedTuple
>>> class Karma(NamedTuple):
...     giver: str
...     receiver: str
...     score: int
...
# 如果输入如下的内容:
# Karma("bob", "julian", "5")
# Python回给出如下的错误信息:
# Argument 3 to  "Karma" has incompatible type "str", expected "int"
# 但是下面这样就可以
????
>>> karma = Karma("bob", "julian", 5)
>>> karma
Karma(giver='bob', receiver='julian', score=5)
为`namedtuple`添加类型提示.png

使用re模块中的findall查找与正则表达式模式匹配的所有实例

使用re模块中的findall查找与正则表达式模式匹配的所有实例:

# Python

>>> tweet = "We love tweeting #Python #tips because it's a beautful #programming language"
>>> import re
>>> re.findall(r"#(\w+)", tweet)
['Python', 'tips', 'programming']
re.findall.png

检查字符串中的所有字符是否都是数字

使用Python中的str.isdigit()方法检查字符串中的所有字符是否都是数字:

# Python

>>> "a".isdigit()
False
>>> "w2".isdigit()
False
>>> "1".isdigit()
True
>>> "690".isdigit()
True
>>> str.isdigit("1")
True
str.isdigit().png

获取所有月份的名称

可以使用Python的calender模块获取所有月份的名称:

# Python

>>> import calendar
>>> months = calendar.month_abbr[1:]
>>> months
['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
>>> months = calendar.month_abbr[:]
>>> months
['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
>>>
>>> months = calendar.month_abbr[1:]
>>>
>>> months_nums_to_names = dict(enumerate(months, start=1))
>>> months_nums_to_names
{1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'}
>>>
>>> {v: k for k, v in months_nums_to_names.items()} # 这里使用了字典推导式,把字典months_nums_to_names中键值对掉个个。
{'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
所有月份.png

获取文件扩展名的两种方法

在Python中获取文件扩展名的两种方法:

# Python

>>> filename = "carbon.png"
>>> from os.path import splitext
>>> splitext(filename)[-1]
'.png'

>>> from pathlib import Path
>>> Path(filename).suffix
'.png'
获取文件扩展名.png

获取日历月

在Python中获取日历月的两种方法:

# Python

>>> import calendar
>>> print(calendar.month(2021, 4))
     April 2021
Mo Tu We Th Fr Sa Su
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

# 想要一个列表中的列表(矩阵)来代替上面的结果吗?
>>> from pprint import pprint as pp
>>> pp(calendar.monthcalendar(2021, 4))
[[0, 0, 0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9, 10, 11],
 [12, 13, 14, 15, 16, 17, 18],
 [19, 20, 21, 22, 23, 24, 25],
 [26, 27, 28, 29, 30, 0, 0]]
日历月.png

通过编程制作gif图

imageio是一个整洁的库,可以借助它通过编程的方式制作gif。

这里我们用它来制作从某个网站上所获取的4个图片的gif文件。

# Python
>>> twitter_img_url = "https://pbs.twimg.com/media/{}?format=jpg&name=small"
>>> tip_images = "Eze6FmFXsAATgRx Eze5EJQWUAEMP9y EzZvI3xX0AE75p_ EzT-nI9UYAEuTr4".split()
>>> from urllib.request import urlretrieve
>>> for img in tip_images:
...     urlretrieve(twitter_img_url.format(img), img)
...
>>> import imageio
>>> images = [imageio.imread(filename) for fileneme in tip_images]
>>> imageio.mimsave("tips.gif", images, duration=1)
制作gif.png

由于上面的网址无法访问,所以用当前目录下的4个图片文件实现生成gif文件的目的:
当前目录下有下列的图片文件:

2021-05-13-11-54-01.png
2021-05-19-10-29-48.png
2021-05-21-11-00-42.png
2021-05-21-14-05-34.png
2021-05-21-15-20-29.png
2021-05-28-11-25-06.png
2021-05-28-11-31-13.png
2021-05-28-11-44-46.png
2021-05-28-11-53-05.png
2021-05-28-14-01-50.png
2021-05-28-14-16-31.png
2021-05-28-14-18-12.png
2021-05-28-14-23-45.png
NLTK_Downloader.png

除了这些扩展名为.png的图片文件外,当前目录下还有其他文件,另外,我们只想使用图片文件列表中第2、3、4、5个图片形成最终的gif文件:

# Python
import os
import imageio

img_list=[]
for i in os.listdir():  #遍历当前文件夹中的所有文件
    if os.path.splitext(i)[1] == ".png":  # 判断文件扩展名是否为“.png”,如果是,则加入列表。
        img_list.append(i)

images = [imageio.imread(fileneme) for fileneme in img_list[1:5]]
imageio.mimsave("new_img.gif", images, duration=1)

本地文件制作gif.png

效果如下:


new_img.gif

获取文件名

从Python中的文件路径获取文件名的两种方法:

# Python

>>> file = "/Users/bobbelderbos/Downloads/carbon.png"
>>>
>>> import os
>>> os.path.basename(file)
'carbon.png'
>>>
>>> from pathlib import Path
>>> Path(file).name
'carbon.png'
获取文件名.png

faker包生成虚拟数据

您的应用需要使用一些虚拟数据吗?使用faker包吧,里面有很多东西!

# Python

>>> from faker import Faker
>>> fake = Faker()
>>> dir(fake)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__',  ..., 'windows_platform_token', 'word', 'words', 'year', 'zip', 'zipcode', 'zipcode_in_state', 'zipcode_plus4']
>>> fake.words()
['spend', 'area', 'president']
>>> fake.words()
['blue', 'century', 'leave']
>>> fake.words()
['tend', 'standard', 'difference']
>>> fake.zipcode()
'84447'
>>> fake.first_name()
'Amy'
>>> fake.last_name()
'Hughes'
>>> fake.last_name()
'Perez'
>>> fake.email()
'[email protected]'
>>> fake.swift()
'UEINGBRDX3O'
虚拟数据.png

itertools.product替换嵌套的for循环

有时用Python的itertools.product来替换嵌套的for循环会很有趣:

# Python

>>> for i in range(1, 4):
...     for j in "AB":
...         print(f"{i}{j}")
...
1A
1B
2A
2B
3A
3B
>>> from itertools import product
>>> for (i, j) in product(range(1, 4), "AB"):
...     print(f"{i}{j}")
...
1A
1B
2A
2B
3A
3B
itertools.product.png

使用itertools进行排列组合

另外一个itertools 的技巧:

问题:给定一个朋友列表,可以形成多少对?

“组合(combinations)”是你的朋友。

“排列(permutations)”在这里不起作用,因为它根据元素的位置将元素视为唯一的,因此 Ana+Juliette 和 Juliette+Ana 被认为是不同的。

# Python

>>> friends = ["Fernando", "Ana", "juliette"]
>>> from itertools import combinations, permutations
>>> list(combinations(friends, 2))
[('Fernando', 'Ana'), ('Fernando', 'juliette'), ('Ana', 'juliette')]
>>> list(permutations(friends, 2))
[('Fernando', 'Ana'), ('Fernando', 'juliette'), ('Ana', 'Fernando'), ('Ana', 'juliette'), ('juliette', 'Fernando'), ('juliette', 'Ana')]
排列组合.png

使用itertools.accumulate计算运行和:

您可以使用Python的itertools.accumulate来计算运行和:

# Python

>>> from itertools import accumulate
>>> sales = [22, 23, 26, 29, 34, 42]
>>> list(accumulate(sales))
[22, 45, 71, 100, 134, 176]
计算运行和.png

内置函数zip

Python的内置函数zip可以在序列上循环两次,并将当前项与前一项进行比较:

# Python

>>> sales = [22, 23, 26, 29, 34, 42]
>>> for yesterday, today in zip(sales, sales[1:]):
...     print(today - yesterday)
...
1
3
3
5
8
zip函数.png

用Python比较两个文件的内容

以下是用Python 中两个文件的方法:

# Python

>echo "hello" > file1
>echo "hello" > file2
>echo "hello world" > file3
>python
>>> import filecmp
>>> filecmp.cmp("file1", "file2")
True
>>> filecmp.cmp("file1", "file3")
False
比较两个文件的内容.png

string模块中的常量

我们都不喜欢重新发明轮子!

Python的string模块中有一些有用的常量,可以在代码中使用它们:

# Python

>>> import string
>>> dir(string)
['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_sentinel_dict', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>> string.digits
'0123456789'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
string模块.png

集合(set)与字典(dictionary)推导式

列表推导式虽然很棒,但是在Python 中还有setdictionary的推导式,它们也非常简洁。

下面的例子中,过滤包含“a”的名称并使用集合推导对其进行去重。 类似地,我们可以使用字典推导式将值与每个名称相关联。

# Python

>>> names = ["Dana", "Ana", "Sara", "Amber", "Joyce", "Dana", "Tim", "Ana"]
>>> {name for name in names if "a" in name.lower()}
{'Amber', 'Sara', 'Ana', 'Dana'} # 集合推导式
>>> {name: 0 for name in names if "a" in name.lower()}
{'Dana': 0, 'Ana': 0, 'Sara': 0, 'Amber': 0} # 字典推导式
集合与字典推导式.png

反转列表

如何在Python中反转列表?有两种方法:

# Python
>>> # 方法一
>>> numbers = [1, 2, 3, 4, 5]
>>> # in place
>>> numbers.reverse()
>>> numbers
[5, 4, 3, 2, 1]
>>> # returning a copy
>>> list(reversed(numbers))
[1, 2, 3, 4, 5]
>>> numbers
[5, 4, 3, 2, 1]
>>> # 方法二:
>>> numbers[::-1]
[1, 2, 3, 4, 5]
图片.png

千分号

Python允许您给数字添加下划线。
这是一种使比较大的数字更具可读性的有用技术,比如表示千分号:

# Python

>>> 1000000000 == 1_000_000_000
True
图片.png

在Python中需要一个唯一的 ID

想要在Python 中使用一个唯一的 ID吗? 请使用uuid模块:

# Python

>>> from uuid import uuid4
>>> uuid4()
UUID('0639eff6-d86b-4170-9a45-d9bef6cca5cb')
uuid.png

让正则表达式停止匹配

正则表达式是贪婪的!

添加一个?使正则表达式不再贪婪; 一旦满足了匹配条件,正则表达式就会停止。

所以在这个例子中(是的,对于HTML解析使用一个库,这只是为了举例)我们这样匹配第一段:

# Python

>>> import re
>>> html = "

Some text.

Some more text.

" >>> re.search("

.*

", html).group() '

Some text.

Some more text.

' >>> re.search("

.*?

", html).group() '

Some text.

'
图片.png

过滤器+lambda与列表表达式

Python的过滤器+lambda还是列表表达式,你喜欢哪个?

# Python

>>> languages = ["Python", "Java", "Perl", "JS", "C++", "Ruby"]
>>> list(filter(lambda lang: lang.startswith("P"), languages))
['Python', 'Perl']
>>> [lang for lang in languages if lang.startswith("P")]
['Python', 'Perl']
过滤器+lambda与列表表达式.png

dateutil 的模糊解析功能

dateutil的模糊解析功能:

# Python

>>> from dateutil.parser import parse
>>> date = "Wed Apr 10 22:39"
>>> parse(date)
datetime.datetime(2021, 4, 10, 22, 39)
`dateutil` .png

集合的操作

Python集合操作是非常强大的:

# Python

>>> group1 = "Tim Jake Sara".split()
>>> group2 = "Ed Sara Julian".split()
>>> set(group1) & set(group2)
{'Sara'}
>>> set(group1) ^ set(group2)
{'Julian', 'Ed', 'Tim', 'Jake'}
>>>
>>> set(group1) - set(group2)
{'Tim', 'Jake'}
>>> set(group2) - set(group1)
{'Julian', 'Ed'}
集合操作.png

引发HTTPError

Python的requests库有一个raise_for_status()方法,该方法在错误请求的情况下会引发 HTTPError:

# Python

>>> import requests
>>> resp = requests.get("https://httpbin.org/status/404")
>>> resp.status_code
404
>>> resp.raise_for_status()
Traceback (most recent call last):
  File "", line 1, in 
  File "D:\Program Files\Python38\lib\site-packages\requests\models.py", line 943, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404
HTTPError.png

使用urlparse将url解析为不同的组件

您可以使用urlparse将url解析为不同的组件:

# Python

>>> url = "https://pybit.es/lessons-from-wooden.html?referer=Twitter"
>>> from urllib.parse import urlparse
>>> parts = urlparse(url)
>>> parts
ParseResult(scheme='https', netloc='pybit.es', path='/lessons-from-wooden.html', params='', query='referer=Twitter', fragment='')
urlparse.png

一行程序验证IP地址

在Python中验证IP地址的一行程序:

# Python

>>> import ipaddress
>>> ipaddress.ip_address("192.168.0.2")
IPv4Address('192.168.0.2')
>>> ipaddress.ip_address("1.0x2.3.4")
Traceback (most recent call last):
  File "", line 1, in 
  File "D:\Program Files\Python38\lib\ipaddress.py", line 53, in ip_address
    raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
ValueError: '1.0x2.3.4' does not appear to be an IPv4 or IPv6 address
验证IP地址.png

itertools.cycle无限循环一个序列

使用itertools.cycle无限循环一个序列,这里我们模拟一个红绿灯:

# Python

>>> from itertools import cycle
>>> lights = "Red Green Amber".split()
>>> states = cycle(lights)
>>> next(states)
'Red'
>>> next(states)
'Green'
>>> next(states)
'Amber'
>>> next(states)
'Red'
>>> next(states)
'Green'
>>> next(states)
'Amber'
itertools.cycle.png

str.translate返回字符串的副本

Python的str.translate返回值是某个字符串的副本,但是其中每个字符都已经是通过给定的转换表进行映射后的结果。

例如,我们使用它来交换大小写元音:

# Python

>>> vowels = "aeiou"
>>> table = {c: c.swapcase() for c in vowels + vowels.upper()}
>>> text = "today is a sUnny dAy"
>>> translation = text.maketrans(table)
>>> text.translate(translation)
'tOdAy Is A sunny day'
str.translate.png

print()使用通配符*

Python的print语句比您想象的更强大:

# Python

>>> name = ["Julian", "Bob", "Martin", "Rodolfo"]
>>> print(*name, sep="\n")
Julian
Bob
Martin
Rodolfo
`print()`使用通配符`*`.png

您可以使用textwrap模块把文本转换成相同列宽的处理:

# Python

>>> text = ("Every great developer you know got there by solving "
... "probelems they were unqualified to solve until they "
... "actuallly did it. - Patrick Mckenzie")
>>> from textwrap import wrap
>>> from pprint import pprint as pp
>>> pp(wrap(text, width=40))
['Every great developer you know got there',
 'by solving probelems they were',
 'unqualified to solve until they',
 'actuallly did it. - Patrick Mckenzie']
>>>
>>> print(wrap(text, width=40))
['Every great developer you know got there', 'by solving probelems they were', 'unqualified to solve until they', 'actuallly did it. - Patrick Mckenzie']
textswap.png

zip_logest的用法

如果您不希望内建的zip被截断,您可以使用itertools模块中的 zip_longest

# Python

>>> names = "ed sarah jake tim george".split()
>>> scores = (11, 22, 33, 44)
>>> dict(zip(names, scores))
{'ed': 11, 'sarah': 22, 'jake': 33, 'tim': 44}
>>> from itertools import zip_longest
>>> dict(zip_longest(names, scores))
{'ed': 11, 'sarah': 22, 'jake': 33, 'tim': 44, 'george': None}
zip_longest.png

open方法的x开关

Python的open内置方法有一个x开关,用于打开文件进行“独占创建”,如果文件已经存在,则会失败:

# Python

>echo file.txt
file.txt
>python
>>> with open("file.txt", "x") as f:
...     f.write("some text")
>>>9
`open`方法的`x`开关.png

查找子字符串在字符串中的位置

可以使用find()rfind()查找子字符串在字符串中的位置:

# Python

>>> text = "today is a beautiful day"
>>> text.find("day")
2
>>> text.rfind("day")
21
>>> text[text.rfind("day"):]
'day'
>>> text.find("dayy")
-1
查找子字符串在字符串中的位置.png

通过数字查找月份名称,通过月份名称查找数字

可以使用calendar.month_abbr从数字中查找月份名称,反之亦然:

# Python

>>> import calendar

>>> {month: index for index, month in enumerate(calendar.month_abbr) if month}
{'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> # 或者想要查找月份的数字:
>>> {index: month for index, month in enumerate(calendar.month_abbr) if month}
{1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'}
数字与月份.png

Python #tip:您可以使用函数的__annotations__属性检查函数的注释:

# Python

>>> def hello(name: str) ->str:
...     return f"Hello {name}"
...
>>> hello.__annotations__
{'name': , 'return': }
检查函数注释.png

python-decouplepython-dotenv

按照Django的应用程序(app)的要求,您应该在环境中存储配置。
python-decouplepython-dotenv库则是用于此目的两个非常优秀的库,比如:

# Python

from decouple import config, Csv

SECRET_KEY = config("SECRET_KEY")
DEBUG = config("DEBUG", default=False, cast=bool)
ALLOWED_HOSTS = config("ALLOWER_HOSTS",  cast = Csv())

:脚本中的decouple来自于python-decouple库的安装,而不是decouple,所以如果在之前误安装了decouple库(不是python-decouple库),则需要把使用pip uninstall decouple命令把不带“python-”前缀的decouple库卸载掉,否则在执行from decouple import config语句时,会出现如下的错误信息:

ImportError: cannot import name 'config' from 'decouple' 
(D:\Program Files\Python38\lib\site-packages\decouple\__init__.py)
decouple与dotenv库.png

splitlines()函数

Python的splitlines()适用于换行符 ("\n") 和回车符 ("\r"):

# Python

>>> line = "some text\r\nsome more text"
>>> line.split("\n")
['some text\r', 'some more text']
>>> line.splitlines()
['some text', 'some more text']
>>>
splitlines()函数.png

让字符串的长度相等

如果希望字符串的宽度相等,可以使用zfill()方法,该方法在开始处添加零:

# Python


>>> for i in range(1, 11):
...     str(i).zfill(3)
...
'001'
'002'
'003'
'004'
'005'
'006'
'007'
'008'
'009'
'010'
让字符串的长度相等.png

对生成器(Generator)进行切片:

您可以使用itertools.islice对生成器(Generator)进行切片:

# Python

>>> def gen():
...     yield from range(1, 11)
...
>>> g = gen()
>>> g[:2]
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'generator' object is not subscriptable
>>> from itertools import islice
>>> list(islice(g, 3, 5))
[4, 5]
对生成器(Generator)进行切片.png

any函数

Python很简洁,读起来就像英语一样!

一个很好的例子就是在本例中将 4 行代码减少为一行代码的any内置函数:

# Python

>>> languages = ["Java", "Perl", "PHP", "Python", "JS", "C++", "JS", "Ruby"]
>>> has_pluses = False
>>> for language in languages:
...     if "++" in language:
...         has_pluses = True
...
>>> has_pluses
True
>>> # 更Python化、更简洁的方式:
>>> any("++" in language for language in languages)
True
any函数.png

删除序列中的重复项

可以使用集合对序列中的项目进行重复数据删除。请注意,它不会保留各个项目在原有序列中的顺序。

# Python

>>> languages = [
...     "Python", "Java", "Perl", "PHP",
...     "Python", "JS", "C++", "JS",
...     "Python", "Ruby",
... ]
>>> languages.count("Python")
3
>>> set(languages)
{'Python', 'Perl', 'Java', 'JS', 'PHP', 'C++', 'Ruby'}
删除序列中的重复项.png

链式链接比较运算符

在#Python 中,您可以像下满这样链接各个比较运算符:

# Python

>>> a, b = 5, 15
>>> 1 < a and a < 10
True
>>> 1 < a < 10
True
>>> 1 < b and b < 10
False
>>> 1 < b < 10
False
链式链接比较运算符.png

sorted()sort()

sorted()返回一个新列表,sort()就地排序:

# Python

>>> friends = "doug kim anthony sara fred joyce".split()
>>> sorted(friends)
['anthony', 'doug', 'fred', 'joyce', 'kim', 'sara']
>>> friends
['doug', 'kim', 'anthony', 'sara', 'fred', 'joyce']

>>>friends.sort()
>>> friends
>>> ['anthony', 'doug', 'fred', 'joyce', 'kim', 'sara']
sorted()与sort().png

获取时间戳:

在Python中获取Unix时间戳很容易:

# Python

>>> import time
>>> time.time()
1622445350.722104
>>> int(time.time())
1622445360
>>> int(time.time())
1622445370
获取时间戳.png

删除缩进和换行

inspect.cleandoc(或textwrap.dedent)可以帮助您删除不需要的缩进和换行,这对于测试是非常有用的:

# Python

>>> actual = "123\n456\n789"
>>> print(actual)
123
456
789
>>> expected = """
...     123
...     456
...     789
... """
>>> assert actual == expected
Traceback (most recent call last):
  File "", line 1, in 
AssertionError
>>> from inspect import cleandoc
>>> cleandoc(expected)
'123\n456\n789'
>>> assert actual == cleandoc(expected)
删除缩进和换行.png

将字节转换为字符串

有时您需要在Python中将字节转换为字符串,您可以使用decode()来实现:

# Python

>>> response = b"pragmatic programmer"
>>> type(response)

>>> "pragmatic" in response
Traceback (most recent call last):
  File "", line 1, in 
TypeError: a bytes-like object is required, not 'str'
>>> response = response.decode("utf-8")
>>> type(response)

>>> "pragmatic" in response
True
将字节转换为字符串.png

f-strings调试/打印变量:

启动Python 3.8 f-strings可以更轻松地调试/打印变量:

# Python

>>> name =  "Jacob"
>>> color = "red"
>>> day = "Saturday"
>>> f"{name=} {color=} {day=}"
"name='Jacob' color='red' day='Saturday'"
f-strings.png

random模块变得可预测:

使用seed使Python的random变得可预测:

# Python

>>> from random import choice, seed
>>> names = ("Jake", "Sara", "Charlie", "Amy", "Doug")
>>> seed(123)
>>> choice(names)
'Jake'
>>> choice(names)
'Charlie'
>>> seed(123)
>>> choice(names)
'Jake'
>>> choice(names)
'Charlie'
图片.png

从序列中选择随机项或进行随机抽样:

Python可以很容易地从序列中选择随机项或进行随机抽样样本:

# Python

>>> colors = ("red", "green", "yellow", "blue", "grey", "orange")
>>> from random import choice, sample
>>> choice(colors)
'blue'
>>> sample(colors, 3) # 3表示抽样数量,colors是样本
['red', 'green', 'yellow']
从序列中选择随机项或进行随机抽样.png

sorted()函数的key关键字参数(函数形式的表达式)

在Python中,内置函数sorted()使用一个可选的key关键字参数(一个函数形式的表达式)进行比较。 在这里,我们使用它按姓氏对学生进行排序:

# Python

>>> students = ["Boblne Scholar", "Clare Cutress",
...             "Levey Noton", "Malynda Izatt",
...             "Prissie Jeenes"]
>>> def get_last_name(full_name):
...     return full_name.split()[-1]
...
>>> sorted(students, key=get_last_name)
['Clare Cutress', 'Malynda Izatt', 'Prissie Jeenes', 'Levey Noton', 'Boblne Scholar']
sorted()函数的key关键字参数.png

string.Template模块

Python的string.Template模块是提前构建字符串的好方法:

# Python

>>> from string import Template
>>> s = Template("Hey $name, congratulations on your $belt Ninja Belt")
>>> s.substitute(name="Tim", belt="Orange")
'Hey Tim, congratulations on your Orange Ninja Belt'
Template.png

循环遍历附加一个计数器:

如果在循环遍历一个iterable时希望值旁边伴随有一个计数器,那么就请使用内置函数enumerate。你甚至可以从1开始:

# Python

>>> names = ("Sara", "Kevin", "Ana", "Tim", "Elisa")
>>> for i, name in enumerate(names, start=1):
...     print(f"{i}, {name}")
...
1, Sara
2, Kevin
3, Ana
4, Tim
5, Elisa
循环遍历附加一个计数器.png

一次从字典中获取多个项目

有没有想过如何一次从字典中获取多个项目?

您可以使用operator模块中的itemgetter实现这个功能:

# Python

>>> workouts = {
...     "mon": "chest+biceps",
...     "tue": "legs",
...     "thurs": "back+triceps",
...     "frt": "legs"
... }
>>> from operator import itemgetter
>>> itemgetter("mon", "frt")(workouts)
('chest+biceps', 'legs')
.png

https://twitter.com/pybites/status/1373173687743045633

你可能感兴趣的:(2021-05-27 Python小技巧)