likes
comments
collection
share

流畅的python--菜鸟小技巧

作者站长头像
站长
· 阅读数 16

对于python菜鸟来说,只看基本教程后的结果就是看是看过了,但依然不会用,遇事先百度; 此文整理了一些python区别于js的一些小技巧(鄙人前端学py),可以快速高效实现功能,当个笔记,后面会持续更新

版本:python3.x

列表推导listcomps和生成器genexps表达式

列表推导和生成器表达式是Python中非常强大和常用的语法。它们可以让你更加简洁和高效地创建和操作列表和生成器。

  • 列表推导是一种用来生成新列表的简洁方式。它允许你在一行代码里使用for循环来对列表进行转换、筛选或者其他操作。例如,下面的代码将生成1到10的平方数列表:
squares = [x**2 for x in range(1, 11)]
print(squares)   # 输出: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

ps:只用列表推导来生成新列表,且尽量保持简短

  • 生成器表达式与列表推导类似,但它们返回一个生成器对象,而不是一个列表对象。生成器表达式的语法和列表推导几乎相同,只是用括号替代了方括号。例如,下面的代码将生成1到10的平方数生成器:
squares = (x**2 for x in range(1, 11))
print(squares)   # 输出: <generator object <genexpr> at 0x7fda8d8f0c10>

生成器表达式的优点是它们可以逐个地生成元素,而不是一次性生成整个列表。这使得生成器表达式在处理大量数据时非常高效(内存中不会留下一个长list)。例如,下面的代码使用生成器表达式来计算1到1000000的平方和:

squares = (x**2 for x in range(1, 1000001))
sum_of_squares = sum(squares)
print(sum_of_squares)   # 输出: 333333833333500000

生成器表达式有很多用途。其中一个是在处理大量数据时节省内存。另一个用途是可以用来创建无限序列,因为生成器可以无限生成元素而不会耗尽内存。例如,下面的代码使用生成器表达式创建了一个无限的斐波那契数列:

fibonacci = (x if x <= 1 else fibonacci[x-2] + fibonacci[x-1] for x in range(0, float('inf')))

这个生成器表达式将不断生成斐波那契数列中的下一个数,直到程序被强制停止或内存不足为止。这种方法可以用来处理需要无限数据的问题,例如流处理或数学问题。

字典和集合推导式

除了列表推导和生成器表达式之外,Python还支持字典推导和集合推导。字典推导和集合推导的语法类似于列表推导,但它们生成的是字典或集合对象。字典推导的语法是{key: value for item in iterable},其中keyvalue是字典键和值的表达式,item是可迭代对象中的每个元素。例如,下面的代码使用字典推导来生成一个从1到10的数字的平方数字典:

squares = {x: x**2 for x in range(1, 11)}
print(squares)   # 输出: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}

集合推导的语法和字典推导类似,只是用花括号替代了方括号。例如,下面的代码使用集合推导来生成一个从1到10的数字的平方集合:

squares = {x**2 for x in range(1, 11)}
print(squares)   # 输出: {64, 1, 4, 36, 9, 16, 49, 81, 25, 100}

美化打印JSON格式

你可以使用Python中的json模块来美化打印JSON格式。具体来说,你可以使用json.dumps()函数,它提供了一个indent参数,用于指定缩进级别。例如,下面的代码演示了如何使用json.dumps()函数来打印一个JSON格式的字典,使其更易读:

import json

my_dict = {'name': 'Alice', 'age': 25, 'friends': ['Bob', 'Charlie', 'David']}

print(json.dumps(my_dict, indent=4))

打印结果:

{
    "name": "Alice",
    "age": 25,
    "friends": [
        "Bob",
        "Charlie",
        "David"
    ]
}

计算程序的执行时间

你可以使用Python内置的time模块来计算程序的执行时间。具体来说,你可以使用time.time()函数来获取当前时间,然后在程序执行结束时再次使用该函数来获取时间并计算差值。例如,下面的代码演示了如何计算一个简单for循环的执行时间:

import time

start_time = time.time()

# 程序代码开始
for i in range(1000000):
    pass
# 程序代码结束

end_time = time.time()

print("程序执行时间:", end_time - start_time, "秒")

这个代码演示了如何使用time模块来计算一个for循环的执行时间。在执行程序时,它将打印出程序执行的总时间(以秒为单位)。你可以将你自己的程序代码放在“程序代码开始”和“程序代码结束”之间,以计算它的执行时间。

在Python中,***运算符的作用区别:

在Python中,***运算符都是用来扩展参数列表的。它们的主要区别在于:

  • *运算符可以用来解包一个可迭代对象(如列表或元组),将它们作为位置参数传递给函数。例如,如果你有一个包含三个元素的列表,你可以使用``运算符将它们解包成三个独立的元素:
    my_list = [1, 2, 3]
    print(*my_list)  # 输出: 1 2 3
  • **运算符则可以用来解包一个字典,将它们作为关键字参数传递给函数。例如,如果你有一个包含两个键值对的字典,你可以使用**运算符将它们解包成两个关键字参数:

    my_dict = {'a': 1, 'b': 2}
    my_function(**my_dict)  # 等同于 my_function(a=1, b=2)

另外,***运算符也可以在函数定义时用来接受任意数量的位置参数和关键字参数。在函数定义时,*args表示可以接受任意数量的位置参数,**kwargs表示可以接受任意数量的关键字参数。例如,下面的代码定义了一个函数,它可以接受任意数量的位置参数和关键字参数:

    def my_function(*args, **kwargs):
        for arg in args:
            print(arg)
        for key, value in kwargs.items():
            print(key, value)

    my_function(1, 2, 3, name='Alice', age=25)
    # 输出:
    # 1
    # 2
    # 3
    # name Alice
    # age 25

在调用函数时,你也可以使用***运算符来传递参数。例如,下面的代码将一个列表和一个字典作为参数传递给函数:

    my_list = [1, 2, 3]
    my_dict = {'name': 'Alice', 'age': 25}
    my_function(*my_list, **my_dict)
    # 输出:
    # 1
    # 2
    # 3
    # name Alice
    # age 25

list.sort 和sorted的异同

list.sort()方法是用来对列表进行排序的,它会改变原列表。该方法没有返回值,因此调用它时不需要赋值。sorted()函数也可以对可迭代对象进行排序,但是它会返回一个新的已排序的列表,不会改变原列表。以下是list.sort()sorted()的参数及其解释:

  • key:指定一个函数,该函数接受一个参数并返回用于排序的键。例如,如果要按照字符串长度对列表进行排序,则可以将key参数设置为len函数。这个参数的默认值是恒等函数(identity function),也就是默认用元素自己的值来排序
  • reverse:如果设置为True,则排序规则会反转,即升序变为降序,降序变为升序。默认为False,即升序排序。

查看一个对象(如模块、类、实例等)的所有方法和属性

你可以使用Python内置的dir()函数来查看一个对象(如模块、类、实例等)的所有方法和属性。例如,下面的代码演示了如何查看Python内置的math模块的所有方法和属性:

    import math

    print(dir(math))

这个代码将打印出math模块的所有方法和属性的列表。你可以将你自己的对象放在dir()函数中,以查看它的所有方法和属性。

用bisect来管理已排序的序列

bisect模块提供了一些用于管理已排序序列的函数。一般来说,这些函数可以被用来搜索序列中某个元素的插入位置,或是查找序列中某个元素的位置。下面是一些常用的函数:

  • bisect.bisect_left(a, x, lo=0, hi=len(a)):在已排序的序列a中查找元素x的插入位置(左侧)。该函数会返回一个整数i,满足以下条件:

    • 对于任意j < i,都有a[j] < x;-
    • 对于任意j >= i,都有a[j] >= x

    参数lohi分别指定了查找的起始位置和结束位置,默认值为0len(a)

  • bisect.bisect_right(a, x, lo=0, hi=len(a)):在已排序的序列a中查找元素x的插入位置(右侧)。该函数会返回一个整数i,满足以下条件:

    • 对于任意j <= i,都有a[j] <= x
    • 对于任意j > i,都有a[j] > x

    参数lohi分别指定了查找的起始位置和结束位置,默认值为0len(a)

  • bisect.bisect(a, x, lo=0, hi=len(a)):在已排序的序列a中查找元素x的插入位置(右侧)。该函数等价于bisect_right函数。

  • bisect.insort_left(a, x, lo=0, hi=len(a)):在已排序的序列a中插入元素x,并保持序列有序(左侧)。该函数会将元素x插入到序列中,使得序列仍然保持有序。该函数没有返回值。参数lohi分别指定了查找的起始位置和结束位置,默认值为0len(a)

  • bisect.insort_right(a, x, lo=0, hi=len(a)):在已排序的序列a中插入元素x,并保持序列有序(右侧)。该函数等价于insort_left函数。

例如,下面的代码演示了如何使用bisect模块来管理已排序的序列:

    import bisect

    a = [1, 3, 4, 5, 6, 8, 9]

    # 在序列a中查找元素2的插入位置(左侧)
    print(bisect.bisect_left(a, 2))  # 输出: 1

    # 在序列a中查找元素7的插入位置(右侧)
    print(bisect.bisect_right(a, 7))  # 输出: 6

    # 在序列a中插入元素7
    bisect.insort_right(a, 7)
    print(a)  # 输出: [1, 3, 4, 5, 6, 7, 8, 9]

关于 if __name__ == 'main':

在Python中,每个模块都有一个__name__属性。如果一个模块是被直接执行的,那么它的__name__属性的值为"main";如果一个模块是被其他模块导入的,那么它的__name__属性的值为模块的名称。因此,当我们编写一个Python程序时,我们可以使用if name == 'main'来判断这个程序是被直接执行还是被其他模块导入。

具体来说,我们可以在Python程序的最后加上以下代码:

    if __name__ == '__main__':
        # 在这里写程序的主逻辑

这段代码的含义是:如果这个程序是被直接执行的,那么就执行if语句中的代码;如果这个程序是被其他模块导入的,那么if语句中的代码不会被执行。这样做的好处是,我们可以在程序中编写一些测试代码,这些代码只有在这个程序被直接执行的时候才会被执行,而在被其他模块导入的时候不会执行。

例如,下面的代码演示了如何使用if __name__ == 'main'来编写一个简单的Python程序:

    def fibonacci(n):
        if n <= 1:
            return n
        else:
            return fibonacci(n-1) + fibonacci(n-2)

    if __name__ == '__main__':
        for i in range(10):
            print(fibonacci(i))

这个程序定义了一个递归函数fibonacci,然后使用if __name__ == 'main'来测试这个函数的正确性。如果这个程序是被直接执行的,那么它会打印出斐波那契数列的前10项;如果这个程序是被其他模块导入的,那么它不会打印任何东西。

快速建立一个web服务

我们可以使用Python内置的http.server模块来快速地建立一个简单的web服务。具体来说,我们可以在一个文件夹中运行以下命令来启动这个服务:

python -m http.server

这个命令会在8000端口上启动一个简单的web服务,然后将当前文件夹中的所有文件都作为静态文件提供出来。例如,如果我们在当前文件夹中有一个名为index.html的文件,那么我们可以通过访问http://localhost:8000/index.html来在浏览器中查看这个文件。

需要注意的是,这个web服务是非常简单的,只能提供静态文件,而不能提供动态内容。如果我们需要提供动态内容,那么就需要使用更加复杂的web框架,例如Django或Flask。