目录
1.字符串格式化的几种方法
- 旧式%方式:
>>> 'Hello, %s' % name
'Hello, Bob'
>>> '%x' % errno
'badc0ffee'
>>> 'Hey %(name)s, there is a 0x%(errno)x error!' % {
... 'name': name, 'errno': errno}
'Hey Bob, there is a 0xbadc0ffee error!'
- 新式format方式:
>>> 'Hello, {}'.format(name)
'Hello, Bob'
>>> 'Hey {name}, there is a 0x{errno:x} error!'.format(name=name, errno=errno)
'Hey Bob, there is a 0xbadc0ffee error!'
- 字符串字面值插值(Python3.6+):
# 1.
>>> f'Hello, {name}!'
'Hello, Bob!'
# 2.
>>> a = 5
>>> b = 10
>>> f'Five plus ten is {a + b} and not {2 * (a + b)}.'
'Five plus ten is 15 and not 30.'
- 模板字符串:
>>> from string import Template
>>> t = Template('Hey, $name!')
>>> t.substitute(name='Bob')
'Hey, Bob!'
- 如何选择格式化方式:
如果格式字符串是用户提供的,使用模板字符串来避免安全问题。如果不是,再考虑Python版本:Python3.6+使用字符串字面值插值,老版则使用“新式”字符串格式化。
2. 函数是Python的头等对象
- 函数是对象
指向函数的变量和函数本身是彼此独立的
- 函数可存储在数据结构中
- 函数可传递给其他函数
能接受其他函数作为参数的函数被称为高阶函数
- 函数可以嵌套
- 函数可捕捉局部状态
内部函数不仅可以从父函数返回,还可以捕获并携带父函数的某些状态,这样的内部函数称为词法闭包(lexical closure),简称闭包。闭包在程序流不在闭包范围的情况下,也能记住封闭作用域(enclosing scope)中的值。
闭包举例:
>>> def get_speak_func(text, volume):
... def whisper():
... return text.lower() + '...'
... def yell():
... return text.upper() + '!'
... if volume > 0.5:
... return yell
... else:
... return whisper
...
>>> get_speak_func('Hello, World', 0.7)()
'HELLO, WORLD!'
whisper和yell就是词法闭包。
- 关于什么是头等对象(first class)也可以参考https://stackoverflow.com/questions/245192/what-are-first-class-objects
- 对象也可以作为函数使用
检查一个对象是否可调用使用callable方法。可以在类中定义__call__方法,则该类的对象可调用。
3. lambda是单表达式函数
lambda函数只能有一个表达式,不能使用注释,不能有返回语句。lambda有一个隐式的返回表达式。
4. 装饰器的力量
- 装饰器是可调用的,将可调用对象作为输入并返回另一个可调用对象。@语法在使用以后就会立即装饰函数,如果想访问未经装饰的原函数比较麻烦。因此如果想保留调用未装饰函数的能力,需要手动装饰需要装饰的函数,不要使用@语法。
- 多个装饰器应用于一个函数时,装饰顺序是从下往上:
def strong(func):
def wrapper():
return '<strong>' + func() + '</strong>'
return wrapper()
def emphasis(func):
def wrapper():
return '<em>' + func() + '</em>'
return wrapper()
@strong
@emphasis
def greet():
return 'Hello!'
greet()
# output:
'<strong><em>Hello!</em></strong>'
- 装饰接受参数的函数
使用位置参数和关键字参数:
def proxy(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
注意:在调用原函数时需要使用*和**对参数解包。
- 保留原函数的元数据(函数名/doc string/参数列表等)需要使用functools.wraps装饰器:
import functools
def uppercase(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs).upper()
return wrapper()