函数的使用方式
- 将函数视为“一等公民”
- 函数可以赋值给变量
- 函数可以作为函数的参数
- 函数可以作为函数的返回值
- 函数可以赋值给变量
高阶函数的用法(
filter
、map
以及它们的替代品)items1 = list(map(lambda x : x ** 2, filter(lambda x : x % 2, range(1, 10)))))
items2 = [x ** 2 for x in range(1, 10) if x % 2]
位置参数、可变参数、关键字参数、命名关键字参数
- 参数的元信息(代码可读性问题)
- 匿名函数和内联函数的用法(
lambda
函数) - 闭包和作用域问题
- Python搜索变量的LEGB顺序(Local >>> Embedded >>> Global >>> Built-in)
global
和nonlocal
关键字的作用global
:声明或定义全局变量(要么直接使用现有的全局作用域的变量,要么定义一个变量放到全局作用域)。nonlocal
:声明使用嵌套作用域的变量(嵌套作用域必须存在该变量,否则报错)
- Python搜索变量的LEGB顺序(Local >>> Embedded >>> Global >>> Built-in)
- 装饰器函数(使用装饰器和取消装饰器)
例子:输出函数执行时间的装饰器 https://www.runoob.com/w3cnote/python-func-decorators.html
from time import time
from functools import wraps
def record_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
print(f'{func.__name__}: {time() - start}s')
return result
return wrapper
如果装饰器不希望跟print
函数耦合,可以编写可以参数化的装饰器
from functools import wraps
from time import time
def record(output):
"""可以参数化的装饰器"""
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
output(func.__name__, time() - start)
return result
return wrapper
return decorate
from functools import wraps
from time import time
class Record():
"""通过定义类的方式定义装饰器"""
def __init__(self, output):
self.output = output
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time()
result = func(*args, **kwargs)
self.output(func.__name__, time() - start)
return result
return wrapper
说明:由于对带装饰功能的函数添加了@wraps装饰器,可以通过
func.__wrapped__
方式获得被装饰之前的函数或类来取消装饰器的作用
例子:用装饰器来实现单例模式
from functools import wraps
def singleton(cls):
"""装饰类的装饰器"""
instances = {}
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class President:
"""总统(单例类)"""
pass
提示:上面的代码中用到了闭包(closure),不知道你是否已经意识到了。还没有一个小问题就是,上面的代码并没有实现线程安全的单例,如果要实现线程安全的单例应该怎么做呢?
线程安全的单例装饰器
from functools import wraps
from threading import RLock
def singleton(cls):
"""线程安全的单例装饰器"""
instances = {}
locker = RLock()
@wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
with locker:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
上面的代码用到了
with
上下文语法来进行锁操作,因为锁对象本身就是上下文管理器对象(支持__enter__
和__exit__
魔术方法)。在wrapper
函数中,我们先做了一次不带锁的检查,然后再做带锁的检查,这样做比直接加锁检查性能要更好,如果对象已经创建就没有必须再去加锁而是直接返回该对象就可以了
面向对象
- 类与类之间的关系
- is-a关系:继承
- has-a关系:关联 / 聚合 / 合成
- use-a关系:依赖
- is-a关系:继承
例子:扑克游戏。
"""
经验:符号常量总是优于字面常量,枚举类型是定义符号常量的最佳选择
"""
from enum import Enum, unique
import random
@unique
class Suite(Enum):
"""花色"""
SPADE, HEART, CLUB, DIAMOND = range(4)
def __lt__(self, other):
return self.value < other.value
class Card():
"""牌"""
def __init__(self, suite, face):
"""初始化方法"""
self.suite = suite
self.face = face
def show(self):
"""显示牌面"""
suites = ['♠︎', '♥︎', '♣︎', '♦︎']
faces = ['', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
return f'{suites[self.suite.value]}{faces[self.face]}'
def __repr__(self):
return self.show()
class Poker():
"""扑克"""
def __init__(self):
self.index = 0
self.cards = [Card(suite, face)
for suite in Suite
for face in range(1, 14)]
def shuffle(self):
"""洗牌(随机乱序)"""
random.shuffle(self.cards)
self.index = 0
def deal(self):
"""发牌"""
card = self.cards[self.index]
self.index += 1
return card
@property
def has_more(self):
return self.index < len(self.cards)
class Player():
"""玩家"""
def __init__(self, name):
self.name = name
self.cards = []
def get_one(self, card):
"""摸一张牌"""
self.cards.append(card)
def sort(self, comp=lambda card: (card.suite, card.face)):
"""整理手上的牌"""
self.cards.sort(key=comp)
def main():
"""主函数"""
poker = Poker()
poker.shuffle()
players = [Player('东邪'), Player('西毒'), Player('南帝'), Player('北丐')]
while poker.has_more:
for player in players:
player.get_one(poker.deal())
for player in players:
player.sort()
print(player.name, end=': ')
print(player.cards)
if __name__ == '__main__':
main()
""" output
东邪: [♠︎A, ♠︎3, ♠︎4, ♠︎6, ♠︎Q, ♥︎2, ♥︎5, ♥︎9, ♣︎2, ♣︎3, ♣︎9, ♦︎8, ♦︎10]
西毒: [♠︎9, ♥︎A, ♥︎4, ♥︎6, ♥︎7, ♥︎8, ♥︎10, ♣︎7, ♣︎10, ♦︎A, ♦︎3, ♦︎6, ♦︎J]
南帝: [♠︎J, ♥︎J, ♥︎Q, ♥︎K, ♣︎4, ♣︎6, ♣︎8, ♣︎J, ♣︎Q, ♦︎4, ♦︎5, ♦︎9, ♦︎Q]
北丐: [♠︎2, ♠︎5, ♠︎7, ♠︎8, ♠︎10, ♠︎K, ♥︎3, ♣︎A, ♣︎5, ♣︎K, ♦︎2, ♦︎7, ♦︎K]
"""
- 关于
unique
&Enum
https://blog.51cto.com/13502993/2147820