跳转至

代码片段参考

Python 是相当便捷的语言,特定的问题都有比较套路化的处理方式。

以下是一些常见的代码处理方式:

1. 使用列表生成器语法

Python 的列表生成器语法可以快速生成列表,在逻辑相对简单时,非常适合。 但要注意的是,过分复杂的处理逻辑会使代码难以阅读。 因此复杂逻辑建议直接使用for循环处理。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 按时间生成 dps 数据
import time
dps = [ [(int(time.time()) + i) * 1000, i ** 2] for i in range(5) ]
dps = list(dps)
print(dps)
# [[1583172382000, 0], [1583172383000, 1], [1583172384000, 4], [1583172385000, 9], [1583172386000, 16]]

# 将输入的 dps 乘方
dps = [
    [1583172563000, 0],
    [1583172564000, 1],
    [1583172565000, 2],
    [1583172566000, 3],
    [1583172567000, 4]
]
dps = [ [d[0], d[1] ** 2] for d in dps ]
dps = list(dps)
print(dps)
# [[1583172563000, 0], [1583172564000, 1], [1583172565000, 4], [1583172566000, 9], [1583172567000, 16]]

2. 使用内置 map 函数处理列表

Python 内置的map函数是另一个方便处理列表的函数。 逻辑简单时,可以使用 lambda 表达式; 逻辑复杂时,可以先定义函数后作为参数传入。

示例如下:

Python
 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
# 使用 lambda 表达式将输入的 dps 乘方
dps = [
    [1583172563000, 0],
    [1583172564000, 1],
    [1583172565000, 2],
    [1583172566000, 3],
    [1583172567000, 4]
]
dps = map(lambda x: [x[0], x[1] ** 2], dps)
dps = list(dps)
print(dps)
# [[1583172563000, 0], [1583172564000, 1], [1583172565000, 4], [1583172566000, 9], [1583172567000, 16]]

# 使用传入函数将输入的 dps 乘方
dps = [
    [1583172563000, 0],
    [1583172564000, 1],
    [1583172565000, 2],
    [1583172566000, 3],
    [1583172567000, 4]
]
def get_pow(x):
    timestamp = x[0]
    value     = x[1] ** 2
    return [timestamp, value]

dps = map(get_pow, dps)
dps = list(dps)
print(dps)
# [[1583172563000, 0], [1583172564000, 1], [1583172565000, 4], [1583172566000, 9], [1583172567000, 16]]

3. 获取 JSON 数据中多层嵌套中的值

有时函数会获取到一个嵌套层数较多的 JSON,同时需要获取某个层级下的值。 可以使用try语法快速获取。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 获取 level3 的值
input_data = {
    'level1': {
        'level2': {
            'level3': 'value'
        }
    }
}
value = None
try:
    value = input_data['level1']['level2']['level3']
except Exception as e:
    pass

print(value)
# value

使用此方法时,try 代码块中不要添加其他任何无关代码,否则可能导致应当抛出的异常被跳过

4. 使用 arrow 库正确处理时间

Python 内置的日期处理模块在使用上有一定复杂度,并且对时区的支持并不好。 在处理时间时,建议使用第三方arrow模块。

arrow 模块已经内置,可直接 import 后使用

示例如下:

Python
 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
import arrow

# 获取当前 Unix 时间戳
print(arrow.utcnow().timestamp)
# 1583174345

# 获取当前北京时间字符串
print(arrow.now('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'))
# 2020-03-03 02:39:05

# 获取当前北京时间的 ISO8601 格式字符串
print(arrow.now('Asia/Shanghai').isoformat())
# 2020-03-03T02:39:05.013290+08:00
#
# 从 Unix 时间戳解析,并输出北京时间字符串
print(arrow.get(1577808000).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'))
# 2020-01-01 00:00:00

# 从 ISO8601 时间字符串解析,并输出北京时间字符串
print(arrow.get('2019-12-31T16:00:00Z').to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'))
# 2020-01-01 00:00:00

# 从非标准时间字符串解析,并作为北京时间字符串
print(arrow.get('2020-01-01 00:00:00', 'YYYY-MM-DD HH:mm:ss').replace(tzinfo='Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'))
# 2020-01-01 00:00:00

# 时间运算:获取前一天,并输出北京时间字符串
print(arrow.get('2019-12-31T16:00:00Z').shift(days=-1).to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss'))
# 2019-12-31 00:00:00

更详细内容,请参考arrow官方文档: https://arrow.readthedocs.io/

5. 向外部发送 HTTP 请求

Python 内置的http处理模块在使用上有一定复杂度。 在发送 http 请求时,建议使用第三方requests模块。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import requests

# 发送 GET 请求
r = requests.get('https://api.github.com/')
print(r.status_code)
print(r.json())

# form 方式发送 POST 请求
r = requests.post('https://httpbin.org/post', data={'key':'value'})
print(r.status_code)
print(r.json())

# json 方式发送 POST 请求
r = requests.post('https://httpbin.org/post', json={'key':'value'})
print(r.status_code)
print(r.json())

更详细内容,请参考requests官方文档: https://requests.readthedocs.io/

6. 发送钉钉机器人消息

钉钉自定义机器人可以简单的通过 POST 请求将消息推送到群中,是作为消息提示的不二选择。 由于只需要发送 HTTP 请求即可,因此可以直接使用requests模块。

示例如下:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import requests

url = 'https://oapi.dingtalk.com/robot/send?access_token=xxxxx'
body = {
    'msgtype': 'text',
    'text': {
        'content': '钉钉机器人提示信息 @180xxxx0000'
    },
    'at': {
        'atMobiles': [
            '180xxxx0000'
        ]
    }
}
requests.post(url, json=body)

新版的钉钉群机器人添加了相关安全验证处理,具体请参考官方文档

更详细内容,请参考钉钉机器人官方文档: https://developers.dingtalk.com/document/app/custom-robot-access

7. 避免 SQL 注入

当需要将函数的传入参数作为 SQL 语句的参数时,需要注意避免 SQL 注入问题。 应当始终使用内置的连接器操作对象提供的sql_params参数,而不要直接拼接 SQL 语句字符串。

以下为正确示例:

Python
1
helper.query('SELECT * FROM table WHERE id = ?', sql_params=[target_id])

以下错误示范:

Python
1
2
helper.query("SELECT * FROM table WHERE id = '{}'".format(target_id))
helper.query("SELECT * FROM table WHERE id = '%s'" % target_id)

实际各类型的连接器操作对象使用方法略有不同,请参考「操作连接器 DFF.CONN(...)」章节

百度百科「SQL 注入」词条: https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5

W3Cschool「MySQL 及 SQL 注入」章节: https://www.w3cschool.cn/mysql/mysql-sql-injection.html