In [1]:
from itertools import product, starmap
import operator as op

product

  • 笛卡尔积

In [2]:
list(product('ABC', range(2)))


Out[2]:
[('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]

enumerate


In [20]:
list(starmap(op.mul, enumerate('ABC', start=2)))


Out[20]:
['AA', 'BBB', 'CCCC']

In [4]:
import threading

help(type(threading.Lock()))


Help on class lock in module _thread:

class lock(builtins.object)
 |  A lock object is a synchronization primitive.  To create a lock,
 |  call threading.Lock().  Methods are:
 |  
 |  acquire() -- lock the lock, possibly blocking until it can be obtained
 |  release() -- unlock of the lock
 |  locked() -- test whether the lock is currently locked
 |  
 |  A lock is not owned by the thread that locked it; another thread may
 |  unlock it.  A thread attempting to lock a lock that it has already locked
 |  will block until another thread unlocks it.  Deadlocks may ensue.
 |  
 |  Methods defined here:
 |  
 |  __enter__(...)
 |      acquire(blocking=True, timeout=-1) -> bool
 |      (acquire_lock() is an obsolete synonym)
 |      
 |      Lock the lock.  Without argument, this blocks if the lock is already
 |      locked (even by the same thread), waiting for another thread to release
 |      the lock, and return True once the lock is acquired.
 |      With an argument, this will only block if the argument is true,
 |      and the return value reflects whether the lock is acquired.
 |      The blocking operation is interruptible.
 |  
 |  __exit__(...)
 |      release()
 |      (release_lock() is an obsolete synonym)
 |      
 |      Release the lock, allowing another thread that is blocked waiting for
 |      the lock to acquire the lock.  The lock must be in the locked state,
 |      but it needn't be locked by the same thread that unlocks it.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  acquire(...)
 |      acquire(blocking=True, timeout=-1) -> bool
 |      (acquire_lock() is an obsolete synonym)
 |      
 |      Lock the lock.  Without argument, this blocks if the lock is already
 |      locked (even by the same thread), waiting for another thread to release
 |      the lock, and return True once the lock is acquired.
 |      With an argument, this will only block if the argument is true,
 |      and the return value reflects whether the lock is acquired.
 |      The blocking operation is interruptible.
 |  
 |  acquire_lock(...)
 |      acquire(blocking=True, timeout=-1) -> bool
 |      (acquire_lock() is an obsolete synonym)
 |      
 |      Lock the lock.  Without argument, this blocks if the lock is already
 |      locked (even by the same thread), waiting for another thread to release
 |      the lock, and return True once the lock is acquired.
 |      With an argument, this will only block if the argument is true,
 |      and the return value reflects whether the lock is acquired.
 |      The blocking operation is interruptible.
 |  
 |  locked(...)
 |      locked() -> bool
 |      (locked_lock() is an obsolete synonym)
 |      
 |      Return whether the lock is in the locked state.
 |  
 |  locked_lock(...)
 |      locked() -> bool
 |      (locked_lock() is an obsolete synonym)
 |      
 |      Return whether the lock is in the locked state.
 |  
 |  release(...)
 |      release()
 |      (release_lock() is an obsolete synonym)
 |      
 |      Release the lock, allowing another thread that is blocked waiting for
 |      the lock to acquire the lock.  The lock must be in the locked state,
 |      but it needn't be locked by the same thread that unlocks it.
 |  
 |  release_lock(...)
 |      release()
 |      (release_lock() is an obsolete synonym)
 |      
 |      Release the lock, allowing another thread that is blocked waiting for
 |      the lock to acquire the lock.  The lock must be in the locked state,
 |      but it needn't be locked by the same thread that unlocks it.