zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Python内置(6)any、数学、callable、序列操作

Python序列 操作 内置 数学 any Callable
2023-06-13 09:15:40 时间

any and all

anyall的功能和简单,却更容易重写你的逻辑片段,使其更加Pythonic。它们接收一个迭代器,其中元素为布尔值。就像名字一样,all只有在全为真的时候返回True,而any只要有一个为真就返回True。

很容易将原来的for循环判断改为简短的语句。例如:1,使用all改写

def validate_responses(responses):
    for response in responses:
        # Make sure that `id` exists
        if 'id' not in response:
            return False
        # Make sure it is a string
        if not isinstance(response['id'], str):
            return False
        # Make sure it is 20 characters
        if len(response['id']) != 20:
            return False

    # If everything was True so far for every
    # response, then we can return True.
    return True

使用all:

def validate_responses(responses):
    return all(
        'id' in response
        and isinstance(response['id'], str)
        and len(response['id']) == 20
        for response in responses
    )

例如,使用any改写:

def contains_palindrome(words):
    for word in words:
        if word == ''.join(reversed(word)):
            return True

    # Found no palindromes in the end
    return False

使用any

def contains_palindrome(words):
    return any(word == ''.join(reversed(word)) for word in words)

abs, divmod, pow and round: 数学基础

这4个函数太过常用,以至于放在了内置模块而不是math模块。效果很简单, abs返回数字的绝对值。如abs(-1)的值为1 divmod返回除法后的(商,余数)。如divmod(7,2) 7除2的结果为(3,1) 商3余1。 pow计算指数。pow(2,10) 2的10次方。 round 返回舍入后的数字。(结果值会舍入至最接近的 10 的负 ndigits 次幂的倍数;如果与两个倍数同样接近,则选用偶数。)

>>> import math
>>> math.pi
3.141592653589793
>>> round(math.pi)
3
>>> round(math.pi, 4)
3.1416
>>> round(1728, -2)
1700

isinstance and issubclass: Runtime type checking

你可能已经知道用type检查类型:

def print_stuff(stuff):
    if type(stuff) is list:
        for item in stuff:
            print(item)
    else:
        print(stuff)

但这存在一个问题,如果我们继承自list 实现一个自定义的类,上面的代码就会失效。

>>> class MyList(list):
...     pass
...
>>> items = MyList(['spam', 'eggs', 'steak'])

原因很简单,现在的typeMylist了。这明显违反了继承的原则,子类应该可以被当作父类使用。这时候就可以用isinstance来检查类型了:

>>> class MyList(list):
...     pass
...
>>> items = ['spam', 'eggs', 'steak']
>>> type(items) is list
True
>>> isinstance(items, list)
True   # Both of these do the same thing
>>> items = MyList(['spam', 'eggs', 'steak'])
>>> type(items) is list
False  # And while `type` doesn't work,
>>> isinstance(items, list)
True   # `isinstance` works with subclasses too.

类似的,issubclass检查一个类是不是另一个类的子类。

>>> issubclass(MyList, list)
True

可以用isinstasnce 修改我们的print_stuff函数,实现对list子类的支持。但如果想对其它容器也提供支持,则需要是使用抽象的容器类:from collections.abc import Container (所有容器类,如list,set都是该类的子类)

from collections.abc import Container

def print_stuff(stuff):
    if isinstance(stuff, Container):
        for item in stuff:
            print(item)
    else:
        print(stuff)

callable 和鸭子类型基础

众所周知,Python被称为“鸭子类型”语言。这意味着Python代码通常倾向于检查对象是否可以满足我们正在寻找的某些行为,而不是关心对象来自的确切类。

Python中的有些东西可以被调用,如函数或类,而有的不行,如整数:

>>> def magic():
...     return 42
...
>>> magic()  # Works fine
42
>>> class MyClass:
...     pass
...
>>> MyClass()  # Also works
<__main__.MyClass object at 0x7f2b7b91f0a0>
>>> x = 42
>>> x()  # Doesn't work
TypeError: 'int' object is not callable

如何检查一个对象是否可被调用?只需要查看是否实现了__call__特殊方法。

>>> def is_callable(item):
...     return hasattr(item, '__call__')
...
>>> is_callable(list)
True
>>> def function():
...     pass
...
>>> is_callable(function)
True
>>> class MyClass:
...     pass
...
>>> is_callable(MyClass)
True
>>> is_callable('abcd')
False

我们的is_callable()几乎和内置的callable功能一样。

>>> callable(list)
True
>>> callable(42)
False

顺便说一句,这些“特殊方法”是Python的大多数语法和功能的工作原理:

  • x()等价于x.__call__()
  • items[10]等价于items.__getitem__(10)
  • a + b等价于a.__add__(b) 几乎每个python行为都有一个潜在的“特殊方法”,或者它们有时被称为“dunder方法”,定义在背后。更多内容见参考文档: python data model

sorted and reversed: 序列操作

sorted可以对传入的可迭代对象进行排序,返回排序后的对象。

>>> items = (3, 4, 1, 2)
>>> sorted(items)
[1, 2, 3, 4]

它有两个参数keyreversekey用于确定排序的标准。 reverse是个布尔值,表示是否反转。

>>> items = [
...   {'value': 3},
...   {'value': 1},
...   {'value': 2},
... ]
>>> sorted(items, key=lambda d: d['value'])
[{'value': 1}, {'value': 2}, {'value': 3}]
>>> names = ['James', 'Kyle', 'Max']
>>> sorted(names, key=len)  # Sorts by name length
['Max', 'Kyle', 'James']

list.sort()sorted很像,但只能对列表使用。

reversed reversed是一个函数,它接收任何序列类型并返回一个生成器,该生成器以相反的顺序生成值。

>>> items = [1, 2, 3]
>>> x = reversed(items)
>>> x
<list_reverseiterator object at 0x7f1c3ebe07f0>
>>> next(x)
3
>>> next(x)
2
>>> next(x)
1
>>> next(x)
StopIteration # Error: end of generator
>>> for i in reversed(items):
...     print(i)
...
3
2
1
>>> list(reversed(items))
[3, 2, 1]