python使用数字与字符串方法技巧

目录
  • 1. 少使用数字字面量
  • 2. 裸字符串处理的问题
  • 3. 展开复杂的计算字面量表达式
  • 4.实用技巧
    • 4.1布尔值也是数字
    • 4.2改善字符串的可读性。
    • 4.3以 r 开头的内建字符串函数。
    • 4.4 float (" inf ")
  • 5.常见误区
    • 5.1“value += 1” 并非线程安全
    • 5.2字符串拼接并不慢

1. 少使用数字字面量

下面的代码使用数字来作为判断条件的语句,如果你从别人手里接手过这部分代码,很难第一时间理解它的意义。

def mark_trip_as_featured(trip):
    """将某个旅程添加到推荐栏目
    """
    if trip.source == 11:
        do_some_thing(trip)
    elif trip.source == 12:
        do_some_other_thing(trip)
    ... ...
    return

我们可以使用枚举的方式,对这些数字部分做一些说明。

from enum import IntEnum

class TripSource(IntEnum):
    FROM_WEBSITE = 11
    FROM_IOS_CLIENT = 12

def mark_trip_as_featured(trip):
    if trip.source == TripSource.FROM_WEBSITE:
        do_some_thing(trip)
    elif trip.source == TripSource.FROM_IOS_CLIENT:
        do_some_other_thing(trip)
    ... ...
    return

将重复出现的数字定义成枚举类型,不仅改善了代码的可读性,还降低了代码出现 Bug 的机率。

当然不是所有的数字都需要用到枚举说明,像常见数字下标 0 和 -1
就不需要。

2. 裸字符串处理的问题

“ 裸字符串处理 ” 这里指只使用基本的加减乘除和循环、配合内置函数/方法来操作字符串,获得我们需要的结果。

def fetch_users(conn, min_level=None, gender=None, has_membership=False, sort_field="created"):
    """获取用户列表
   
    :param int min_level: 要求的最低用户级别,默认为所有级别
    :param int gender: 筛选用户性别,默认为所有性别
    :param int has_membership: 筛选所有会员/非会员用户,默认非会员
    :param str sort_field: 排序字段,默认为按 created "用户创建日期"
    :returns: 列表:[(User ID, User Name), ...]
    """
    # 一种古老的 SQL 拼接技巧,使用 "WHERE 1=1" 来简化字符串拼接操作
    # 区分查询 params 来避免 SQL 注入问题
    statement = "SELECT id, name FROM users WHERE 1=1"
    params = []
    if min_level is not None:
        statement += " AND level >= ?"
        params.append(min_level)
    if gender is not None:
        statement += " AND gender >= ?"
        params.append(gender)
    if has_membership:
        statement += " AND has_membership == true"
    else:
        statement += " AND has_membership == false"
    
    statement += " ORDER BY ?"
    params.append(sort_field)
    return list(conn.execute(statement, params))

这样做虽然看起来简单,符合直觉,但是随着函数逻辑变得复杂,这段代码会变得容易出错。

更好的选择是利用一些开源的对象化模块来操作他们。
这里使用了 SQLAlchemy

def fetch_users_v2(conn, min_level=None, gender=None, has_membership=False, sort_field="created"):
    """获取用户列表
    """
    query = select([users.c.id, users.c.name])
    if min_level is not None:
        query = query.where(users.c.level >= min_level)
    if gender is not None:
        query = query.where(users.c.gender == gender)
    query = query.where(users.c.has_membership == has_membership).order_by(users.c[sort_field])
    return list(conn.execute(query))

其它的替换思路:

Q: 目标/源字符串是结构化的,遵循某种格式吗?

其它的开源的对象化模块。

  • SQL:SQLAlchemy
  • XML:lxml
  • JSON、YAML …

尝试使用模板引擎而不是复杂字符串处理逻辑来达到目的。

  • Jinja2
  • Mako
  • Mustache

3. 展开复杂的计算字面量表达式

def f1(delta_seconds):
    # 如果时间已经过去了超过 11 天,不做任何事
    if delta_seconds > 950400:
        return 
    ...

“为什么我们不直接把代码写成 if delta_seconds < 11 * 24 * 3600: 呢?”

“性能”,答案一定会是“性能”。 Python 是一门解释型语言,所以预先计算出 950400 正是因为我们不想让每次对函数 f1 的调用都带上这部分的计算开销。

不过事实是:即使我们把代码改成 if delta_seconds < 11 * 24 * 3600:,函数也不会多出任何额外的开销。

当我们的代码中需要出现复杂计算的字面量时,请保留整个算式吧。它对性能没有任何影响,而且会增加代码的可读性。

def f1(delta_seconds):
    if delta_seconds < 11 * 24 * 3600:
        return

4.实用技巧

4.1布尔值也是数字

True False 可以当成 1 和 0 使用

>>> True + 1
2
>>> 1 / False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

计数简化操作。

>>> l = [1, 2, 4, 5, 7]
>>> sum(i % 2 == 0 for i in l)
2

如果将某个布尔值表达式作为列表的下标使用,可以实现类似三元表达式的目的:

# 类似的三元表达式:"Javascript" if 2 > 1 else "Python"
>>> ["Python", "Javascript"][2 > 1]
'Javascript'

4.2改善字符串的可读性。

对于字符串我们常使用 \ 和 + 来讲字符串拆分成好几段。

还有一种简单的方法是用 ()。
用 ()括起来就可以随意拆行了。

s = (
    "There is something really bad happened during the process. "
    "Please contact your administrator."
)

对于多级缩进字符串:

可以调用其他的标准库来达到简化效果。

from textwrap import dedent

def main():
    if user.is_active:
        # dedent 将会缩进掉整段文字最左边的空字符串
        message = dedent("""\
            Welcome, today's movie list:
            - Jaw (1975)
            - The Shining (1980)
            - Saw (2004)""")

大数字也可以变得更加可阅读:

在数字之间加入下划线。

>>> 10_000_000.0  # 以“千”为单位划分数字
10000000.0
>>> 0xCAFE_F00D  # 16进制数字同样有效,4个一组更易读
3405705229
>>> 0b_0011_1111_0100_1110  # 二进制也有效
16206
>>> int('0b_1111_0000', 2)  # 处理字符串的时候也会正确处理下划线
240

4.3以 r 开头的内建字符串函数。

例如 : .split() 和 .rsplit() 的区别是,一个从左到右分割字符串,另一个是从右到左处理字符串。

合理使用一些现成 string 操作函数可以让工作事半功倍。

4.4 float (" inf ")

float ( " inf " ) float ( " -inf ") ,对应着无穷大和无穷小。

float( " -inf ") < 任意数值 < float( " inf ")

一些可以用上的场合。

# A. 根据年龄升序排序,没有提供年龄放在最后边
>>> users = {"tom": 19, "jenny": 13, "jack": None, "andrew": 43}
>>> sorted(users.keys(), key=lambda user: users.get(user) or float('inf'))
['jenny', 'tom', 'andrew', 'jack']

# B. 作为循环初始值,简化第一次判断逻辑
>>> max_num = float('-inf')
>>> # 找到列表中最大的数字
>>> for i in [23, 71, 3, 21, 8]:
...:    if i > max_num:
...:         max_num = i
...:
>>> max_num
71

5.常见误区

5.1“value += 1” 并非线程安全

如下:这个操作并不是线程安全的。

这个简单的累加语句,会被编译成包括取值和保存在内的好几个不同步骤。

而在多线程环境下,任意一个其他线程都有可能在其中某个步骤切入进来,阻碍你获得正确的结果。

def incr(value):
    value += 1

# 使用 dis 模块查看字节码
import dis

dis.dis(incr)
      0 LOAD_FAST                0 (value)
      2 LOAD_CONST               1 (1)
      4 INPLACE_ADD
      6 STORE_FAST               0 (value)
      8 LOAD_CONST               0 (None)
     10 RETURN_VALUE

常用 dis 模块去验证自己的操作,有时候,结果和我们预想的并不一样。

5.2字符串拼接并不慢

Python 的字符串拼接(+=)在 2.2 以及之前的版本确实很慢。
但之后的版本做了更新,效率已经大大提升,所有字符串的拼接还是可以使用的。

到此这篇关于python使用数字与字符串方法技巧的文章就介绍到这了,更多相关python数字与字符串内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python不使用int()函数把字符串转换为数字的方法

    不使用int()函数的情况下把字符串转换为数字,如把字符串"12345"转换为数字12345. 方法一:利用str函数 既然不能用int函数,那我们就反其道而行,用str函数找出每一位字符表示的数字大写. def atoi(s): s = s[::-1] num = 0 for i, v in enumerate(s): for j in range(0, 10): if v == str(j): num += j * (10 ** i) return num 方法二:利用ord函数

  • Python随机函数random随机获取数字、字符串、列表等使用详解

    在python中用于生成随机数的模块是random,在使用前需要import, 下面看下它的用法. Python随机生成一个浮点数 random.random random.random()用于生成一个0到1的随机符点数: 0 <= n < 1.0 注意: 以下代码在Python3.5下测试通过, python2版本可稍加修改 描述 random() 方法返回随机生成的一个实数,它在(0,1)范围内. 语法 以下是 random() 方法的语法: import random random.ra

  • python使用数字与字符串方法技巧

    目录 1. 少使用数字字面量 2. 裸字符串处理的问题 3. 展开复杂的计算字面量表达式 4.实用技巧 4.1布尔值也是数字 4.2改善字符串的可读性. 4.3以 r 开头的内建字符串函数. 4.4 float (" inf ") 5.常见误区 5.1“value += 1” 并非线程安全 5.2字符串拼接并不慢 1. 少使用数字字面量 下面的代码使用数字来作为判断条件的语句,如果你从别人手里接手过这部分代码,很难第一时间理解它的意义. def mark_trip_as_feature

  • Python常用数据结构和公共方法技巧总结

    目录 1. 列表 1.1 列表的定义 1.2 列表常用操作 1.3 循环遍历 1.4 应用场景 2. 元组 2.1 元组的定义 2.2 元组常用操作 2.3 循环遍历 2.4 应用场景 3. 字典 3.1 字典的定义 3.2 字典常用操作 3.3 循环遍历 3.4 应用场景 4. 字符串 4.1 字符串的定义 4.2 字符串的常用操作 1) 判断类型 2) 查找和替换 3) 大小写转换 4) 文本对齐 5) 去除空白字符 6) 拆分和连接 4.3 字符串的切片 4.4 字符串的格式化输出 5.

  • Python 的内置字符串方法小结

    字符串处理是非常常用的技能,但 Python 内置字符串方法太多,常常遗忘,为了便于快速参考,特地依据 Python 3.5.1 给每个内置方法写了示例并进行了归类,便于大家索引. PS: 可以点击概览内的绿色标题进入相应分类或者通过右侧边栏文章目录快速索引相应方法. 大小写转换 str.capitalize() 将首字母转换成大写,需要注意的是如果首字没有大写形式,则返回原字符串. 'adi dog'.capitalize() # 'Adi dog' 'abcd 徐'.capitalize()

  • 详解python的数字类型变量与其方法

    前言 python数据类型是不允许改变的,这就意味着如果改变 Number 数据类型的值,将重新分配内存空间.下面话不多说,来看看详细的介绍吧. 以下实例在变量赋值时 Number 对象将被创建: var1 = 1 var2 = 10 您也可以使用del语句删除一些 Number 对象引用. 您可以通过使用del语句删除单个或多个对象,例如: del var del var_a, var_b Python 支持四种不同的数值类型: 整型(Int)               - 通常被称为是整型

  • python 实现数字字符串左侧补零的方法

    因为做新闻爬虫,url里面0-9的日期要左侧加零.经过查询之后得到了两种方法. 一.先设一个足够大的数,比如1000000,然后加上当前的数字比如9,得到1000009,然后转化为字符串获取第6.7位即可.下面以1000为例. k=1000 #k是用来获取01 02 03 字符串的 1001 截取第三四位 即可 for i in range(1,31): strtime=i+k time=str(strtime)[2:4] print(len(time)) 二.先获取当前字符串长度,然后用预期长

  • Python常见格式化字符串方法小结【百分号与format方法】

    本文实例讲述了Python常见格式化字符串方法.分享给大家供大家参考,具体如下: [方式一]百分号(%)方式,类C的printf,需要分别不同类型. 1.匿名tuple.(推荐在参数少时用) >>> '姓名:%s, 年龄:%d' % ('walker', 99) '姓名:walker, 年龄:99' 2.命名dict,字典的key可以重用. >>> '姓名:%(name)s, 年龄:%(age)d, 工龄:%(age)d' % {'name':'walker', 'ag

  • Python实现简单文本字符串处理的方法

    本文实例讲述了Python实现简单文本字符串处理的方法.分享给大家供大家参考,具体如下: 对于一个文本字符串,可以使用Python的string.split()方法将其切割.下面看看实际运行效果. mySent = 'This book is the best book on python!' print mySent.split() 输出: ['This', 'book', 'is', 'the', 'best', 'book', 'on', 'python!'] 可以看到,切分的效果不错,但

  • Python实现针对给定字符串寻找最长非重复子串的方法

    本文实例讲述了Python实现针对给定字符串寻找最长非重复子串的方法.分享给大家供大家参考,具体如下: 问题: 给定一个字符串,寻找其中最长的重复子序列,如果字符串是单个字符组成的话如"aaaaaaaaaaaaa"那么满足要求的输出就是a 思路: 这里的思路有两种是我能想到的 (1)从头开始遍历字符串,设置标志位,在往后走的过程中当发现和之前标志位重合的时候就回头检查一下这个新出现的子串是否跟前面字符串或者前面字符串的子串相同,相同则记录该子串并计数加1,直至处理完毕 (2)利用滑窗切

  • Python去除、替换字符串空格的处理方法

    个人想到的解决方法有两种,一种是  .replace(' old ',' new ')   第一个参数是需要换掉的内容比如空格,第二个是替换成的内容,可以把字符串中的空格全部替换掉. 第二种方法是像这样 str_1_data = ' a b c ' str_2_list = str_1_data.split() str_1 = '' for i in range(len(str_2_list)): #这里可以直接用 str_1.join(str2_list) str_1 += str_2_lis

  • Python基础学习之基本数据结构详解【数字、字符串、列表、元组、集合、字典】

    本文实例讲述了Python基础学习之基本数据结构.分享给大家供大家参考,具体如下: 前言 相比于PHP,Python同样也是脚本解析语言,所以在使用Python的时候,变量和数据结构相对于编译语言来说都会简单许多,但是Python相比于PHP来说,变量类型的定义会比较严格:string->int的转换没有PHP那么方便.但这也让程序稳定性有所提升,例如和客户端交互的时候,数据库取出来的数字int和缓存取出来的数字(默认是string)需要手动进行转换(否则会有报错提示),而PHP不需要手动转换的

随机推荐